json.hpp
1    //     __ _____ _____ _____
2    //  __|  |   __|     |   | |  JSON for Modern C++
3    // |  |  |__   |  |  | | | |  version 3.11.3
4    // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5    //
6    // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
7    // SPDX-License-Identifier: MIT
8    
9    /****************************************************************************\ 
10    * Note on documentation: The source files contain links to the online      * 
11    * documentation of the public API at https://json.nlohmann.me. This URL    * 
12    * contains the most recent documentation and should also be applicable to  * 
13    * previous versions; documentation for deprecated functions is not         * 
14    * removed, but marked deprecated. See "Generate documentation" section in  * 
15    * file docs/README.md.                                                     * 
16   \****************************************************************************/
17   
18   #ifndef INCLUDE_NLOHMANN_JSON_HPP_
19   #define INCLUDE_NLOHMANN_JSON_HPP_
20   
21   #include <algorithm> // all_of, find, for_each
22   #include <cstddef> // nullptr_t, ptrdiff_t, size_t
23   #include <functional> // hash, less
24   #include <initializer_list> // initializer_list
25   #ifndef JSON_NO_IO
26       #include <iosfwd> // istream, ostream
27   #endif  // JSON_NO_IO
28   #include <iterator> // random_access_iterator_tag
29   #include <memory> // unique_ptr
30   #include <string> // string, stoi, to_string
31   #include <utility> // declval, forward, move, pair, swap
32   #include <vector> // vector
33   
34   // #include <nlohmann/adl_serializer.hpp>
35   //     __ _____ _____ _____
36   //  __|  |   __|     |   | |  JSON for Modern C++
37   // |  |  |__   |  |  | | | |  version 3.11.3
38   // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
39   //
40   // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
41   // SPDX-License-Identifier: MIT
42   
43   
44   
45   #include <utility>
46   
47   // #include <nlohmann/detail/abi_macros.hpp>
48   //     __ _____ _____ _____
49   //  __|  |   __|     |   | |  JSON for Modern C++
50   // |  |  |__   |  |  | | | |  version 3.11.3
51   // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
52   //
53   // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
54   // SPDX-License-Identifier: MIT
55   
56   
57   
58   // This file contains all macro definitions affecting or depending on the ABI
59   
60   #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61       #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62           #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
63               #warning "Already included a different version of the library!"
64           #endif
65       #endif
66   #endif
67   
68   #define NLOHMANN_JSON_VERSION_MAJOR 3   // NOLINT(modernize-macro-to-enum)
69   #define NLOHMANN_JSON_VERSION_MINOR 11  // NOLINT(modernize-macro-to-enum)
70   #define NLOHMANN_JSON_VERSION_PATCH 3   // NOLINT(modernize-macro-to-enum)
71   
72   #ifndef JSON_DIAGNOSTICS
73       #define JSON_DIAGNOSTICS 0
74   #endif
75   
76   #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
77       #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
78   #endif
79   
80   #if JSON_DIAGNOSTICS
81       #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
82   #else
83       #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
84   #endif
85   
86   #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
87       #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
88   #else
89       #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
90   #endif
91   
92   #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
93       #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
94   #endif
95   
96   // Construct the namespace ABI tags component
97   #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
98   #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ 
99       NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
100  
101  #define NLOHMANN_JSON_ABI_TAGS                                       \ 
102      NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \ 
103              NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \ 
104              NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
105  
106  // Construct the namespace version component
107  #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ 
108      _v ## major ## _ ## minor ## _ ## patch
109  #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ 
110      NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
111  
112  #if NLOHMANN_JSON_NAMESPACE_NO_VERSION
113  #define NLOHMANN_JSON_NAMESPACE_VERSION
114  #else
115  #define NLOHMANN_JSON_NAMESPACE_VERSION                                 \ 
116      NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ 
117                                             NLOHMANN_JSON_VERSION_MINOR, \ 
118                                             NLOHMANN_JSON_VERSION_PATCH)
119  #endif
120  
121  // Combine namespace components
122  #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
123  #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ 
124      NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
125  
126  #ifndef NLOHMANN_JSON_NAMESPACE
127  #define NLOHMANN_JSON_NAMESPACE               \ 
128      nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ 
129              NLOHMANN_JSON_ABI_TAGS,           \ 
130              NLOHMANN_JSON_NAMESPACE_VERSION)
131  #endif
132  
133  #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
134  #define NLOHMANN_JSON_NAMESPACE_BEGIN                \ 
135      namespace nlohmann                               \ 
136      {                                                \ 
137      inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ 
138                  NLOHMANN_JSON_ABI_TAGS,              \ 
139                  NLOHMANN_JSON_NAMESPACE_VERSION)     \ 
140      {
141  #endif
142  
143  #ifndef NLOHMANN_JSON_NAMESPACE_END
144  #define NLOHMANN_JSON_NAMESPACE_END                                     \ 
145      }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \ 
146      }  // namespace nlohmann
147  #endif
148  
149  // #include <nlohmann/detail/conversions/from_json.hpp>
150  //     __ _____ _____ _____
151  //  __|  |   __|     |   | |  JSON for Modern C++
152  // |  |  |__   |  |  | | | |  version 3.11.3
153  // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
154  //
155  // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
156  // SPDX-License-Identifier: MIT
157  
158  
159  
160  #include <algorithm> // transform
161  #include <array> // array
162  #include <forward_list> // forward_list
163  #include <iterator> // inserter, front_inserter, end
164  #include <map> // map
165  #ifdef JSON_HAS_CPP_17
166      #include <optional> // optional
167  #endif
168  #include <string> // string
169  #include <tuple> // tuple, make_tuple
170  #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
171  #include <unordered_map> // unordered_map
172  #include <utility> // pair, declval
173  #include <valarray> // valarray
174  
175  
176  // #include <nlohmann/detail/exceptions.hpp>
177  //     __ _____ _____ _____
178  //  __|  |   __|     |   | |  JSON for Modern C++
179  // |  |  |__   |  |  | | | |  version 3.11.3
180  // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
181  //
182  // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
183  // SPDX-License-Identifier: MIT
184  
185  
186  
187  #include <cstddef> // nullptr_t
188  #include <exception> // exception
189  #if JSON_DIAGNOSTICS
190      #include <numeric> // accumulate
191  #endif
192  #include <stdexcept> // runtime_error
193  #include <string> // to_string
194  #include <vector> // vector
195  
196  // #include <nlohmann/detail/value_t.hpp>
197  //     __ _____ _____ _____
198  //  __|  |   __|     |   | |  JSON for Modern C++
199  // |  |  |__   |  |  | | | |  version 3.11.3
200  // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
201  //
202  // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
203  // SPDX-License-Identifier: MIT
204  
205  
206  
207  #include <array> // array
208  #include <cstddef> // size_t
209  #include <cstdint> // uint8_t
210  #include <string> // string
211  
212  // #include <nlohmann/detail/macro_scope.hpp>
213  //     __ _____ _____ _____
214  //  __|  |   __|     |   | |  JSON for Modern C++
215  // |  |  |__   |  |  | | | |  version 3.11.3
216  // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
217  //
218  // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
219  // SPDX-License-Identifier: MIT
220  
221  
222  
223  #include <utility> // declval, pair
224  // #include <nlohmann/detail/meta/detected.hpp>
225  //     __ _____ _____ _____
226  //  __|  |   __|     |   | |  JSON for Modern C++
227  // |  |  |__   |  |  | | | |  version 3.11.3
228  // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
229  //
230  // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
231  // SPDX-License-Identifier: MIT
232  
233  
234  
235  #include <type_traits>
236  
237  // #include <nlohmann/detail/meta/void_t.hpp>
238  //     __ _____ _____ _____
239  //  __|  |   __|     |   | |  JSON for Modern C++
240  // |  |  |__   |  |  | | | |  version 3.11.3
241  // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
242  //
243  // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
244  // SPDX-License-Identifier: MIT
245  
246  
247  
248  // #include <nlohmann/detail/abi_macros.hpp>
249  
250  
251  NLOHMANN_JSON_NAMESPACE_BEGIN
252  namespace detail
253  {
254  
255  template<typename ...Ts> struct make_void
256  {
257      using type = void;
258  };
259  template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
260  
261  }  // namespace detail
262  NLOHMANN_JSON_NAMESPACE_END
263  
264  
265  NLOHMANN_JSON_NAMESPACE_BEGIN
266  namespace detail
267  {
268  
269  // https://en.cppreference.com/w/cpp/experimental/is_detected
270  struct nonesuch
271  {
272      nonesuch() = delete;
273      ~nonesuch() = delete;
274      nonesuch(nonesuch const&) = delete;
275      nonesuch(nonesuch const&&) = delete;
276      void operator=(nonesuch const&) = delete;
277      void operator=(nonesuch&&) = delete;
278  };
279  
280  template<class Default,
281           class AlwaysVoid,
282           template<class...> class Op,
283           class... Args>
284  struct detector
285  {
286      using value_t = std::false_type;
287      using type = Default;
288  };
289  
290  template<class Default, template<class...> class Op, class... Args>
291  struct detector<Default, void_t<Op<Args...>>, Op, Args...>
292  {
293      using value_t = std::true_type;
294      using type = Op<Args...>;
295  };
296  
297  template<template<class...> class Op, class... Args>
298  using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
299  
300  template<template<class...> class Op, class... Args>
301  struct is_detected_lazy : is_detected<Op, Args...> { };
302  
303  template<template<class...> class Op, class... Args>
304  using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
305  
306  template<class Default, template<class...> class Op, class... Args>
307  using detected_or = detector<Default, void, Op, Args...>;
308  
309  template<class Default, template<class...> class Op, class... Args>
310  using detected_or_t = typename detected_or<Default, Op, Args...>::type;
311  
312  template<class Expected, template<class...> class Op, class... Args>
313  using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
314  
315  template<class To, template<class...> class Op, class... Args>
316  using is_detected_convertible =
317      std::is_convertible<detected_t<Op, Args...>, To>;
318  
319  }  // namespace detail
320  NLOHMANN_JSON_NAMESPACE_END
321  
322  // #include <nlohmann/thirdparty/hedley/hedley.hpp>
323  
324  
325  //     __ _____ _____ _____
326  //  __|  |   __|     |   | |  JSON for Modern C++
327  // |  |  |__   |  |  | | | |  version 3.11.3
328  // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
329  //
330  // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
331  // SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
332  // SPDX-License-Identifier: MIT
333  
334  /* Hedley - https://nemequ.github.io/hedley 
335   * Created by Evan Nemerson <evan@nemerson.com> 
336   */
337  
338  #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
339  #if defined(JSON_HEDLEY_VERSION)
340      #undef JSON_HEDLEY_VERSION
341  #endif
342  #define JSON_HEDLEY_VERSION 15
343  
344  #if defined(JSON_HEDLEY_STRINGIFY_EX)
345      #undef JSON_HEDLEY_STRINGIFY_EX
346  #endif
347  #define JSON_HEDLEY_STRINGIFY_EX(x) #x
348  
349  #if defined(JSON_HEDLEY_STRINGIFY)
350      #undef JSON_HEDLEY_STRINGIFY
351  #endif
352  #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
353  
354  #if defined(JSON_HEDLEY_CONCAT_EX)
355      #undef JSON_HEDLEY_CONCAT_EX
356  #endif
357  #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
358  
359  #if defined(JSON_HEDLEY_CONCAT)
360      #undef JSON_HEDLEY_CONCAT
361  #endif
362  #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
363  
364  #if defined(JSON_HEDLEY_CONCAT3_EX)
365      #undef JSON_HEDLEY_CONCAT3_EX
366  #endif
367  #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
368  
369  #if defined(JSON_HEDLEY_CONCAT3)
370      #undef JSON_HEDLEY_CONCAT3
371  #endif
372  #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
373  
374  #if defined(JSON_HEDLEY_VERSION_ENCODE)
375      #undef JSON_HEDLEY_VERSION_ENCODE
376  #endif
377  #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
378  
379  #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
380      #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
381  #endif
382  #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
383  
384  #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
385      #undef JSON_HEDLEY_VERSION_DECODE_MINOR
386  #endif
387  #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
388  
389  #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
390      #undef JSON_HEDLEY_VERSION_DECODE_REVISION
391  #endif
392  #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
393  
394  #if defined(JSON_HEDLEY_GNUC_VERSION)
395      #undef JSON_HEDLEY_GNUC_VERSION
396  #endif
397  #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
398      #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
399  #elif defined(__GNUC__)
400      #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
401  #endif
402  
403  #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
404      #undef JSON_HEDLEY_GNUC_VERSION_CHECK
405  #endif
406  #if defined(JSON_HEDLEY_GNUC_VERSION)
407      #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
408  #else
409      #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
410  #endif
411  
412  #if defined(JSON_HEDLEY_MSVC_VERSION)
413      #undef JSON_HEDLEY_MSVC_VERSION
414  #endif
415  #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
416      #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
417  #elif defined(_MSC_FULL_VER) && !defined(__ICL)
418      #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
419  #elif defined(_MSC_VER) && !defined(__ICL)
420      #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
421  #endif
422  
423  #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
424      #undef JSON_HEDLEY_MSVC_VERSION_CHECK
425  #endif
426  #if !defined(JSON_HEDLEY_MSVC_VERSION)
427      #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
428  #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
429      #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
430  #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
431      #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
432  #else
433      #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
434  #endif
435  
436  #if defined(JSON_HEDLEY_INTEL_VERSION)
437      #undef JSON_HEDLEY_INTEL_VERSION
438  #endif
439  #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
440      #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
441  #elif defined(__INTEL_COMPILER) && !defined(__ICL)
442      #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
443  #endif
444  
445  #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
446      #undef JSON_HEDLEY_INTEL_VERSION_CHECK
447  #endif
448  #if defined(JSON_HEDLEY_INTEL_VERSION)
449      #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
450  #else
451      #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
452  #endif
453  
454  #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
455      #undef JSON_HEDLEY_INTEL_CL_VERSION
456  #endif
457  #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
458      #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
459  #endif
460  
461  #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
462      #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
463  #endif
464  #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
465      #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
466  #else
467      #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
468  #endif
469  
470  #if defined(JSON_HEDLEY_PGI_VERSION)
471      #undef JSON_HEDLEY_PGI_VERSION
472  #endif
473  #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
474      #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
475  #endif
476  
477  #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
478      #undef JSON_HEDLEY_PGI_VERSION_CHECK
479  #endif
480  #if defined(JSON_HEDLEY_PGI_VERSION)
481      #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
482  #else
483      #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
484  #endif
485  
486  #if defined(JSON_HEDLEY_SUNPRO_VERSION)
487      #undef JSON_HEDLEY_SUNPRO_VERSION
488  #endif
489  #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
490      #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
491  #elif defined(__SUNPRO_C)
492      #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
493  #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
494      #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
495  #elif defined(__SUNPRO_CC)
496      #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
497  #endif
498  
499  #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
500      #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
501  #endif
502  #if defined(JSON_HEDLEY_SUNPRO_VERSION)
503      #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
504  #else
505      #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
506  #endif
507  
508  #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
509      #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
510  #endif
511  #if defined(__EMSCRIPTEN__)
512      #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
513  #endif
514  
515  #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
516      #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
517  #endif
518  #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
519      #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
520  #else
521      #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
522  #endif
523  
524  #if defined(JSON_HEDLEY_ARM_VERSION)
525      #undef JSON_HEDLEY_ARM_VERSION
526  #endif
527  #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
528      #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
529  #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
530      #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
531  #endif
532  
533  #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
534      #undef JSON_HEDLEY_ARM_VERSION_CHECK
535  #endif
536  #if defined(JSON_HEDLEY_ARM_VERSION)
537      #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
538  #else
539      #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
540  #endif
541  
542  #if defined(JSON_HEDLEY_IBM_VERSION)
543      #undef JSON_HEDLEY_IBM_VERSION
544  #endif
545  #if defined(__ibmxl__)
546      #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
547  #elif defined(__xlC__) && defined(__xlC_ver__)
548      #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
549  #elif defined(__xlC__)
550      #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
551  #endif
552  
553  #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
554      #undef JSON_HEDLEY_IBM_VERSION_CHECK
555  #endif
556  #if defined(JSON_HEDLEY_IBM_VERSION)
557      #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
558  #else
559      #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
560  #endif
561  
562  #if defined(JSON_HEDLEY_TI_VERSION)
563      #undef JSON_HEDLEY_TI_VERSION
564  #endif
565  #if \ 
566      defined(__TI_COMPILER_VERSION__) && \ 
567      ( \ 
568        defined(__TMS470__) || defined(__TI_ARM__) || \ 
569        defined(__MSP430__) || \ 
570        defined(__TMS320C2000__) \ 
571      )
572  #if (__TI_COMPILER_VERSION__ >= 16000000)
573      #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
574  #endif
575  #endif
576  
577  #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
578      #undef JSON_HEDLEY_TI_VERSION_CHECK
579  #endif
580  #if defined(JSON_HEDLEY_TI_VERSION)
581      #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
582  #else
583      #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
584  #endif
585  
586  #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
587      #undef JSON_HEDLEY_TI_CL2000_VERSION
588  #endif
589  #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
590      #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
591  #endif
592  
593  #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
594      #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
595  #endif
596  #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
597      #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
598  #else
599      #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
600  #endif
601  
602  #if defined(JSON_HEDLEY_TI_CL430_VERSION)
603      #undef JSON_HEDLEY_TI_CL430_VERSION
604  #endif
605  #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
606      #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
607  #endif
608  
609  #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
610      #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
611  #endif
612  #if defined(JSON_HEDLEY_TI_CL430_VERSION)
613      #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
614  #else
615      #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
616  #endif
617  
618  #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
619      #undef JSON_HEDLEY_TI_ARMCL_VERSION
620  #endif
621  #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
622      #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
623  #endif
624  
625  #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
626      #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
627  #endif
628  #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
629      #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
630  #else
631      #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
632  #endif
633  
634  #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
635      #undef JSON_HEDLEY_TI_CL6X_VERSION
636  #endif
637  #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
638      #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
639  #endif
640  
641  #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
642      #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
643  #endif
644  #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
645      #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
646  #else
647      #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
648  #endif
649  
650  #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
651      #undef JSON_HEDLEY_TI_CL7X_VERSION
652  #endif
653  #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
654      #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
655  #endif
656  
657  #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
658      #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
659  #endif
660  #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
661      #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
662  #else
663      #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
664  #endif
665  
666  #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
667      #undef JSON_HEDLEY_TI_CLPRU_VERSION
668  #endif
669  #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
670      #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
671  #endif
672  
673  #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
674      #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
675  #endif
676  #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
677      #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
678  #else
679      #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
680  #endif
681  
682  #if defined(JSON_HEDLEY_CRAY_VERSION)
683      #undef JSON_HEDLEY_CRAY_VERSION
684  #endif
685  #if defined(_CRAYC)
686      #if defined(_RELEASE_PATCHLEVEL)
687          #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
688      #else
689          #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
690      #endif
691  #endif
692  
693  #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
694      #undef JSON_HEDLEY_CRAY_VERSION_CHECK
695  #endif
696  #if defined(JSON_HEDLEY_CRAY_VERSION)
697      #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
698  #else
699      #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
700  #endif
701  
702  #if defined(JSON_HEDLEY_IAR_VERSION)
703      #undef JSON_HEDLEY_IAR_VERSION
704  #endif
705  #if defined(__IAR_SYSTEMS_ICC__)
706      #if __VER__ > 1000
707          #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
708      #else
709          #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
710      #endif
711  #endif
712  
713  #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
714      #undef JSON_HEDLEY_IAR_VERSION_CHECK
715  #endif
716  #if defined(JSON_HEDLEY_IAR_VERSION)
717      #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
718  #else
719      #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
720  #endif
721  
722  #if defined(JSON_HEDLEY_TINYC_VERSION)
723      #undef JSON_HEDLEY_TINYC_VERSION
724  #endif
725  #if defined(__TINYC__)
726      #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
727  #endif
728  
729  #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
730      #undef JSON_HEDLEY_TINYC_VERSION_CHECK
731  #endif
732  #if defined(JSON_HEDLEY_TINYC_VERSION)
733      #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
734  #else
735      #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
736  #endif
737  
738  #if defined(JSON_HEDLEY_DMC_VERSION)
739      #undef JSON_HEDLEY_DMC_VERSION
740  #endif
741  #if defined(__DMC__)
742      #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
743  #endif
744  
745  #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
746      #undef JSON_HEDLEY_DMC_VERSION_CHECK
747  #endif
748  #if defined(JSON_HEDLEY_DMC_VERSION)
749      #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
750  #else
751      #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
752  #endif
753  
754  #if defined(JSON_HEDLEY_COMPCERT_VERSION)
755      #undef JSON_HEDLEY_COMPCERT_VERSION
756  #endif
757  #if defined(__COMPCERT_VERSION__)
758      #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
759  #endif
760  
761  #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
762      #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
763  #endif
764  #if defined(JSON_HEDLEY_COMPCERT_VERSION)
765      #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
766  #else
767      #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
768  #endif
769  
770  #if defined(JSON_HEDLEY_PELLES_VERSION)
771      #undef JSON_HEDLEY_PELLES_VERSION
772  #endif
773  #if defined(__POCC__)
774      #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
775  #endif
776  
777  #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
778      #undef JSON_HEDLEY_PELLES_VERSION_CHECK
779  #endif
780  #if defined(JSON_HEDLEY_PELLES_VERSION)
781      #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
782  #else
783      #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
784  #endif
785  
786  #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
787      #undef JSON_HEDLEY_MCST_LCC_VERSION
788  #endif
789  #if defined(__LCC__) && defined(__LCC_MINOR__)
790      #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
791  #endif
792  
793  #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
794      #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
795  #endif
796  #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
797      #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
798  #else
799      #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
800  #endif
801  
802  #if defined(JSON_HEDLEY_GCC_VERSION)
803      #undef JSON_HEDLEY_GCC_VERSION
804  #endif
805  #if \ 
806      defined(JSON_HEDLEY_GNUC_VERSION) && \ 
807      !defined(__clang__) && \ 
808      !defined(JSON_HEDLEY_INTEL_VERSION) && \ 
809      !defined(JSON_HEDLEY_PGI_VERSION) && \ 
810      !defined(JSON_HEDLEY_ARM_VERSION) && \ 
811      !defined(JSON_HEDLEY_CRAY_VERSION) && \ 
812      !defined(JSON_HEDLEY_TI_VERSION) && \ 
813      !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ 
814      !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ 
815      !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ 
816      !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ 
817      !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ 
818      !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ 
819      !defined(__COMPCERT__) && \ 
820      !defined(JSON_HEDLEY_MCST_LCC_VERSION)
821      #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
822  #endif
823  
824  #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
825      #undef JSON_HEDLEY_GCC_VERSION_CHECK
826  #endif
827  #if defined(JSON_HEDLEY_GCC_VERSION)
828      #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
829  #else
830      #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
831  #endif
832  
833  #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
834      #undef JSON_HEDLEY_HAS_ATTRIBUTE
835  #endif
836  #if \ 
837    defined(__has_attribute) && \ 
838    ( \ 
839      (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ 
840    )
841  #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
842  #else
843  #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
844  #endif
845  
846  #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
847      #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
848  #endif
849  #if defined(__has_attribute)
850      #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
851  #else
852      #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
853  #endif
854  
855  #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
856      #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
857  #endif
858  #if defined(__has_attribute)
859      #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
860  #else
861      #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
862  #endif
863  
864  #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
865      #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
866  #endif
867  #if \ 
868      defined(__has_cpp_attribute) && \ 
869      defined(__cplusplus) && \ 
870      (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
871      #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
872  #else
873      #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
874  #endif
875  
876  #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
877      #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
878  #endif
879  #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
880      #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
881  #elif \ 
882      !defined(JSON_HEDLEY_PGI_VERSION) && \ 
883      !defined(JSON_HEDLEY_IAR_VERSION) && \ 
884      (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ 
885      (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
886      #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
887  #else
888      #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
889  #endif
890  
891  #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
892      #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
893  #endif
894  #if defined(__has_cpp_attribute) && defined(__cplusplus)
895      #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
896  #else
897      #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
898  #endif
899  
900  #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
901      #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
902  #endif
903  #if defined(__has_cpp_attribute) && defined(__cplusplus)
904      #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
905  #else
906      #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
907  #endif
908  
909  #if defined(JSON_HEDLEY_HAS_BUILTIN)
910      #undef JSON_HEDLEY_HAS_BUILTIN
911  #endif
912  #if defined(__has_builtin)
913      #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
914  #else
915      #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
916  #endif
917  
918  #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
919      #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
920  #endif
921  #if defined(__has_builtin)
922      #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
923  #else
924      #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
925  #endif
926  
927  #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
928      #undef JSON_HEDLEY_GCC_HAS_BUILTIN
929  #endif
930  #if defined(__has_builtin)
931      #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
932  #else
933      #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
934  #endif
935  
936  #if defined(JSON_HEDLEY_HAS_FEATURE)
937      #undef JSON_HEDLEY_HAS_FEATURE
938  #endif
939  #if defined(__has_feature)
940      #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
941  #else
942      #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
943  #endif
944  
945  #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
946      #undef JSON_HEDLEY_GNUC_HAS_FEATURE
947  #endif
948  #if defined(__has_feature)
949      #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
950  #else
951      #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
952  #endif
953  
954  #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
955      #undef JSON_HEDLEY_GCC_HAS_FEATURE
956  #endif
957  #if defined(__has_feature)
958      #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
959  #else
960      #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
961  #endif
962  
963  #if defined(JSON_HEDLEY_HAS_EXTENSION)
964      #undef JSON_HEDLEY_HAS_EXTENSION
965  #endif
966  #if defined(__has_extension)
967      #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
968  #else
969      #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
970  #endif
971  
972  #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
973      #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
974  #endif
975  #if defined(__has_extension)
976      #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
977  #else
978      #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
979  #endif
980  
981  #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
982      #undef JSON_HEDLEY_GCC_HAS_EXTENSION
983  #endif
984  #if defined(__has_extension)
985      #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
986  #else
987      #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
988  #endif
989  
990  #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
991      #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
992  #endif
993  #if defined(__has_declspec_attribute)
994      #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
995  #else
996      #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
997  #endif
998  
999  #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1000     #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1001 #endif
1002 #if defined(__has_declspec_attribute)
1003     #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1004 #else
1005     #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1006 #endif
1007 
1008 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1009     #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1010 #endif
1011 #if defined(__has_declspec_attribute)
1012     #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1013 #else
1014     #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1015 #endif
1016 
1017 #if defined(JSON_HEDLEY_HAS_WARNING)
1018     #undef JSON_HEDLEY_HAS_WARNING
1019 #endif
1020 #if defined(__has_warning)
1021     #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1022 #else
1023     #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1024 #endif
1025 
1026 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1027     #undef JSON_HEDLEY_GNUC_HAS_WARNING
1028 #endif
1029 #if defined(__has_warning)
1030     #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1031 #else
1032     #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1033 #endif
1034 
1035 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1036     #undef JSON_HEDLEY_GCC_HAS_WARNING
1037 #endif
1038 #if defined(__has_warning)
1039     #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1040 #else
1041     #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1042 #endif
1043 
1044 #if \ 
1045     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 
1046     defined(__clang__) || \ 
1047     JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 
1048     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1049     JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 
1050     JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 
1051     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1052     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1053     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 
1054     JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 
1055     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 
1056     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ 
1057     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1058     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1059     JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ 
1060     JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ 
1061     JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ 
1062     (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1063     #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1064 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1065     #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1066 #else
1067     #define JSON_HEDLEY_PRAGMA(value)
1068 #endif
1069 
1070 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1071     #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1072 #endif
1073 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1074     #undef JSON_HEDLEY_DIAGNOSTIC_POP
1075 #endif
1076 #if defined(__clang__)
1077     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1078     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1079 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1080     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1081     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1082 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1083     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1084     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1085 #elif \ 
1086     JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 
1087     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1088     #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1089     #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1090 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1091     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1092     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1093 #elif \ 
1094     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1095     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1096     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ 
1097     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 
1098     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1099     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1100     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1101     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1102 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1103     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1104     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1105 #else
1106     #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1107     #define JSON_HEDLEY_DIAGNOSTIC_POP
1108 #endif
1109 
1110 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for 
1111    HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
1112 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1113     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1114 #endif
1115 #if defined(__cplusplus)
1116 #  if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1117 #    if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1118 #      if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1119 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 
1120     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
1121     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 
1122     _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 
1123     _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ 
1124     xpr \ 
1125     JSON_HEDLEY_DIAGNOSTIC_POP
1126 #      else
1127 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 
1128     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
1129     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 
1130     _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 
1131     xpr \ 
1132     JSON_HEDLEY_DIAGNOSTIC_POP
1133 #      endif
1134 #    else
1135 #      define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 
1136     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
1137     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 
1138     xpr \ 
1139     JSON_HEDLEY_DIAGNOSTIC_POP
1140 #    endif
1141 #  endif
1142 #endif
1143 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1144     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1145 #endif
1146 
1147 #if defined(JSON_HEDLEY_CONST_CAST)
1148     #undef JSON_HEDLEY_CONST_CAST
1149 #endif
1150 #if defined(__cplusplus)
1151 #  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1152 #elif \ 
1153   JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ 
1154   JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ 
1155   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1156 #  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ 
1157         JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
1158         JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ 
1159         ((T) (expr)); \ 
1160         JSON_HEDLEY_DIAGNOSTIC_POP \ 
1161     }))
1162 #else
1163 #  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1164 #endif
1165 
1166 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
1167     #undef JSON_HEDLEY_REINTERPRET_CAST
1168 #endif
1169 #if defined(__cplusplus)
1170     #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1171 #else
1172     #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1173 #endif
1174 
1175 #if defined(JSON_HEDLEY_STATIC_CAST)
1176     #undef JSON_HEDLEY_STATIC_CAST
1177 #endif
1178 #if defined(__cplusplus)
1179     #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1180 #else
1181     #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1182 #endif
1183 
1184 #if defined(JSON_HEDLEY_CPP_CAST)
1185     #undef JSON_HEDLEY_CPP_CAST
1186 #endif
1187 #if defined(__cplusplus)
1188 #  if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1189 #    define JSON_HEDLEY_CPP_CAST(T, expr) \ 
1190     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
1191     _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ 
1192     ((T) (expr)) \ 
1193     JSON_HEDLEY_DIAGNOSTIC_POP
1194 #  elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1195 #    define JSON_HEDLEY_CPP_CAST(T, expr) \ 
1196     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
1197     _Pragma("diag_suppress=Pe137") \ 
1198     JSON_HEDLEY_DIAGNOSTIC_POP
1199 #  else
1200 #    define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1201 #  endif
1202 #else
1203 #  define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1204 #endif
1205 
1206 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1207     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1208 #endif
1209 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1210     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1211 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1212     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1213 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1214     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1215 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1216     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1217 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1218     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1219 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1220     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1221 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1222     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1223 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1224     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1225 #elif \ 
1226     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1227     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1228     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1229     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1230     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1231     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1232     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1233     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1234     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1235     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1236     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1237     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1238 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1239     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1240 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1241     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1242 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1243     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1244 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1245     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1246 #else
1247     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1248 #endif
1249 
1250 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1251     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1252 #endif
1253 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1254     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1255 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1256     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1257 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1258     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1259 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1260     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1261 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1262     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1263 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1264     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1265 #elif \ 
1266     JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ 
1267     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 
1268     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1269     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1270     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1271 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1272     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1273 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1274     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1275 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1276     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1277 #else
1278     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1279 #endif
1280 
1281 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1282     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1283 #endif
1284 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1285     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1286 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1287     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1288 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1289     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1290 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1291     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1292 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1293     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1294 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1295     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1296 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1297     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1298 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1299     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1300 #elif \ 
1301     JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 
1302     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 
1303     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1304     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1305 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1306     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1307 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1308     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1309 #else
1310     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1311 #endif
1312 
1313 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1314     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1315 #endif
1316 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1317     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1318 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1319     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1320 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1321     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1322 #else
1323     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1324 #endif
1325 
1326 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1327     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1328 #endif
1329 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1330     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1331 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1332     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1333 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1334     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1335 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1336     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1337 #else
1338     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1339 #endif
1340 
1341 #if defined(JSON_HEDLEY_DEPRECATED)
1342     #undef JSON_HEDLEY_DEPRECATED
1343 #endif
1344 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
1345     #undef JSON_HEDLEY_DEPRECATED_FOR
1346 #endif
1347 #if \ 
1348     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 
1349     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1350     #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1351     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1352 #elif \ 
1353     (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 
1354     JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 
1355     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1356     JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 
1357     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ 
1358     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 
1359     JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 
1360     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ 
1361     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 
1362     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1363     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ 
1364     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1365     #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1366     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1367 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
1368     #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1369     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1370 #elif \ 
1371     JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ 
1372     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 
1373     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1374     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1375     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1376     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1377     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1378     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1379     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1380     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1381     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1382     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1383     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1384     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1385     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 
1386     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1387     #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1388     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1389 #elif \ 
1390     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 
1391     JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ 
1392     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1393     #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1394     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1395 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1396     #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1397     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1398 #else
1399     #define JSON_HEDLEY_DEPRECATED(since)
1400     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1401 #endif
1402 
1403 #if defined(JSON_HEDLEY_UNAVAILABLE)
1404     #undef JSON_HEDLEY_UNAVAILABLE
1405 #endif
1406 #if \ 
1407     JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ 
1408     JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ 
1409     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1410     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1411     #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1412 #else
1413     #define JSON_HEDLEY_UNAVAILABLE(available_since)
1414 #endif
1415 
1416 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1417     #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1418 #endif
1419 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1420     #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1421 #endif
1422 #if \ 
1423     JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ 
1424     JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 
1425     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1426     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1427     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1428     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1429     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1430     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1431     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1432     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1433     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1434     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1435     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1436     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1437     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 
1438     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 
1439     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1440     #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1441     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1442 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1443     #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1444     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1445 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1446     #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1447     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1448 #elif defined(_Check_return_) /* SAL */
1449     #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1450     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1451 #else
1452     #define JSON_HEDLEY_WARN_UNUSED_RESULT
1453     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1454 #endif
1455 
1456 #if defined(JSON_HEDLEY_SENTINEL)
1457     #undef JSON_HEDLEY_SENTINEL
1458 #endif
1459 #if \ 
1460     JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ 
1461     JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 
1462     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1463     JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 
1464     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1465     #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1466 #else
1467     #define JSON_HEDLEY_SENTINEL(position)
1468 #endif
1469 
1470 #if defined(JSON_HEDLEY_NO_RETURN)
1471     #undef JSON_HEDLEY_NO_RETURN
1472 #endif
1473 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1474     #define JSON_HEDLEY_NO_RETURN __noreturn
1475 #elif \ 
1476     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1477     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1478     #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1479 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1480     #define JSON_HEDLEY_NO_RETURN _Noreturn
1481 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
1482     #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1483 #elif \ 
1484     JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ 
1485     JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ 
1486     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 
1487     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1488     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1489     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1490     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1491     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1492     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1493     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1494     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1495     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1496     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1497     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1498     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1499     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1500     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1501     #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1502 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1503     #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1504 #elif \ 
1505     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 
1506     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1507     #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1508 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1509     #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1510 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1511     #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1512 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1513     #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1514 #else
1515     #define JSON_HEDLEY_NO_RETURN
1516 #endif
1517 
1518 #if defined(JSON_HEDLEY_NO_ESCAPE)
1519     #undef JSON_HEDLEY_NO_ESCAPE
1520 #endif
1521 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1522     #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1523 #else
1524     #define JSON_HEDLEY_NO_ESCAPE
1525 #endif
1526 
1527 #if defined(JSON_HEDLEY_UNREACHABLE)
1528     #undef JSON_HEDLEY_UNREACHABLE
1529 #endif
1530 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1531     #undef JSON_HEDLEY_UNREACHABLE_RETURN
1532 #endif
1533 #if defined(JSON_HEDLEY_ASSUME)
1534     #undef JSON_HEDLEY_ASSUME
1535 #endif
1536 #if \ 
1537     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 
1538     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1539     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1540     #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1541 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1542     #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1543 #elif \ 
1544     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 
1545     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1546     #if defined(__cplusplus)
1547         #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1548     #else
1549         #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1550     #endif
1551 #endif
1552 #if \ 
1553     (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ 
1554     JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 
1555     JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ 
1556     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1557     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ 
1558     JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ 
1559     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1560     #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1561 #elif defined(JSON_HEDLEY_ASSUME)
1562     #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1563 #endif
1564 #if !defined(JSON_HEDLEY_ASSUME)
1565     #if defined(JSON_HEDLEY_UNREACHABLE)
1566         #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1567     #else
1568         #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1569     #endif
1570 #endif
1571 #if defined(JSON_HEDLEY_UNREACHABLE)
1572     #if  \ 
1573         JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 
1574         JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1575         #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1576     #else
1577         #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1578     #endif
1579 #else
1580     #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1581 #endif
1582 #if !defined(JSON_HEDLEY_UNREACHABLE)
1583     #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1584 #endif
1585 
1586 JSON_HEDLEY_DIAGNOSTIC_PUSH
1587 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1588     #pragma clang diagnostic ignored "-Wpedantic"
1589 #endif
1590 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1591     #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1592 #endif
1593 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1594     #if defined(__clang__)
1595         #pragma clang diagnostic ignored "-Wvariadic-macros"
1596     #elif defined(JSON_HEDLEY_GCC_VERSION)
1597         #pragma GCC diagnostic ignored "-Wvariadic-macros"
1598     #endif
1599 #endif
1600 #if defined(JSON_HEDLEY_NON_NULL)
1601     #undef JSON_HEDLEY_NON_NULL
1602 #endif
1603 #if \ 
1604     JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ 
1605     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 
1606     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1607     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1608     #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1609 #else
1610     #define JSON_HEDLEY_NON_NULL(...)
1611 #endif
1612 JSON_HEDLEY_DIAGNOSTIC_POP
1613 
1614 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
1615     #undef JSON_HEDLEY_PRINTF_FORMAT
1616 #endif
1617 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1618     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1619 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1620     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1621 #elif \ 
1622     JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ 
1623     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 
1624     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1625     JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 
1626     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1627     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1628     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1629     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1630     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1631     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1632     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1633     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1634     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1635     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1636     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1637     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1638     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1639     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1640 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1641     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1642 #else
1643     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1644 #endif
1645 
1646 #if defined(JSON_HEDLEY_CONSTEXPR)
1647     #undef JSON_HEDLEY_CONSTEXPR
1648 #endif
1649 #if defined(__cplusplus)
1650     #if __cplusplus >= 201103L
1651         #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1652     #endif
1653 #endif
1654 #if !defined(JSON_HEDLEY_CONSTEXPR)
1655     #define JSON_HEDLEY_CONSTEXPR
1656 #endif
1657 
1658 #if defined(JSON_HEDLEY_PREDICT)
1659     #undef JSON_HEDLEY_PREDICT
1660 #endif
1661 #if defined(JSON_HEDLEY_LIKELY)
1662     #undef JSON_HEDLEY_LIKELY
1663 #endif
1664 #if defined(JSON_HEDLEY_UNLIKELY)
1665     #undef JSON_HEDLEY_UNLIKELY
1666 #endif
1667 #if defined(JSON_HEDLEY_UNPREDICTABLE)
1668     #undef JSON_HEDLEY_UNPREDICTABLE
1669 #endif
1670 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1671     #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1672 #endif
1673 #if \ 
1674   (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ 
1675   JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ 
1676   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1677 #  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(  (expr), (value), (probability))
1678 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability)   __builtin_expect_with_probability(!!(expr),    1   , (probability))
1679 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability)  __builtin_expect_with_probability(!!(expr),    0   , (probability))
1680 #  define JSON_HEDLEY_LIKELY(expr)                      __builtin_expect                 (!!(expr),    1                  )
1681 #  define JSON_HEDLEY_UNLIKELY(expr)                    __builtin_expect                 (!!(expr),    0                  )
1682 #elif \ 
1683   (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 
1684   JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 
1685   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1686   (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 
1687   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1688   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1689   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1690   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 
1691   JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 
1692   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 
1693   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 
1694   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1695   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1696   JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ 
1697   JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 
1698   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1699 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) \ 
1700     (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1701 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ 
1702     (__extension__ ({ \ 
1703         double hedley_probability_ = (probability); \ 
1704         ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ 
1705     }))
1706 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ 
1707     (__extension__ ({ \ 
1708         double hedley_probability_ = (probability); \ 
1709         ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ 
1710     }))
1711 #  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
1712 #  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1713 #else
1714 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1715 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1716 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1717 #  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1718 #  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1719 #endif
1720 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
1721     #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1722 #endif
1723 
1724 #if defined(JSON_HEDLEY_MALLOC)
1725     #undef JSON_HEDLEY_MALLOC
1726 #endif
1727 #if \ 
1728     JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ 
1729     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 
1730     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1731     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 
1732     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1733     JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 
1734     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1735     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1736     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1737     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1738     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1739     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1740     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1741     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1742     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1743     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1744     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1745     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1746     #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1747 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1748     #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1749 #elif \ 
1750     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 
1751     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1752     #define JSON_HEDLEY_MALLOC __declspec(restrict)
1753 #else
1754     #define JSON_HEDLEY_MALLOC
1755 #endif
1756 
1757 #if defined(JSON_HEDLEY_PURE)
1758     #undef JSON_HEDLEY_PURE
1759 #endif
1760 #if \ 
1761   JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ 
1762   JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ 
1763   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1764   JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 
1765   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1766   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1767   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1768   (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1769   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1770   (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1771   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1772   (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1773   JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1774   (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1775   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1776   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1777   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1778   JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 
1779   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1780 #  define JSON_HEDLEY_PURE __attribute__((__pure__))
1781 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1782 #  define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1783 #elif defined(__cplusplus) && \ 
1784     ( \ 
1785       JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 
1786       JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ 
1787       JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ 
1788     )
1789 #  define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1790 #else
1791 #  define JSON_HEDLEY_PURE
1792 #endif
1793 
1794 #if defined(JSON_HEDLEY_CONST)
1795     #undef JSON_HEDLEY_CONST
1796 #endif
1797 #if \ 
1798     JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ 
1799     JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ 
1800     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1801     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 
1802     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1803     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1804     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1805     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1806     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1807     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1808     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1809     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1810     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1811     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1812     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1813     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1814     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1815     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 
1816     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1817     #define JSON_HEDLEY_CONST __attribute__((__const__))
1818 #elif \ 
1819     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1820     #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1821 #else
1822     #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1823 #endif
1824 
1825 #if defined(JSON_HEDLEY_RESTRICT)
1826     #undef JSON_HEDLEY_RESTRICT
1827 #endif
1828 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1829     #define JSON_HEDLEY_RESTRICT restrict
1830 #elif \ 
1831     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 
1832     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 
1833     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1834     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 
1835     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1836     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1837     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 
1838     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1839     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ 
1840     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 
1841     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1842     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ 
1843     JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 
1844     defined(__clang__) || \ 
1845     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1846     #define JSON_HEDLEY_RESTRICT __restrict
1847 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1848     #define JSON_HEDLEY_RESTRICT _Restrict
1849 #else
1850     #define JSON_HEDLEY_RESTRICT
1851 #endif
1852 
1853 #if defined(JSON_HEDLEY_INLINE)
1854     #undef JSON_HEDLEY_INLINE
1855 #endif
1856 #if \ 
1857     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 
1858     (defined(__cplusplus) && (__cplusplus >= 199711L))
1859     #define JSON_HEDLEY_INLINE inline
1860 #elif \ 
1861     defined(JSON_HEDLEY_GCC_VERSION) || \ 
1862     JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1863     #define JSON_HEDLEY_INLINE __inline__
1864 #elif \ 
1865     JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 
1866     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 
1867     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1868     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ 
1869     JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 
1870     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 
1871     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 
1872     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1873     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1874     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1875     #define JSON_HEDLEY_INLINE __inline
1876 #else
1877     #define JSON_HEDLEY_INLINE
1878 #endif
1879 
1880 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
1881     #undef JSON_HEDLEY_ALWAYS_INLINE
1882 #endif
1883 #if \ 
1884   JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ 
1885   JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 
1886   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1887   JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 
1888   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1889   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1890   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1891   (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1892   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1893   (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1894   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1895   (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1896   JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1897   (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1898   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1899   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1900   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1901   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 
1902   JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1903 #  define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1904 #elif \ 
1905   JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 
1906   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1907 #  define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1908 #elif defined(__cplusplus) && \ 
1909     ( \ 
1910       JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1911       JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1912       JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1913       JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 
1914       JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1915       JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ 
1916     )
1917 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1918 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1919 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1920 #else
1921 #  define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1922 #endif
1923 
1924 #if defined(JSON_HEDLEY_NEVER_INLINE)
1925     #undef JSON_HEDLEY_NEVER_INLINE
1926 #endif
1927 #if \ 
1928     JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ 
1929     JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 
1930     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1931     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 
1932     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1933     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 
1934     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 
1935     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1936     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 
1937     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1938     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 
1939     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1940     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 
1941     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1942     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 
1943     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 
1944     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 
1945     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 
1946     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1947     #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1948 #elif \ 
1949     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 
1950     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1951     #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1952 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1953     #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1954 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1955     #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1956 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1957     #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1958 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1959     #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1960 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1961     #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1962 #else
1963     #define JSON_HEDLEY_NEVER_INLINE
1964 #endif
1965 
1966 #if defined(JSON_HEDLEY_PRIVATE)
1967     #undef JSON_HEDLEY_PRIVATE
1968 #endif
1969 #if defined(JSON_HEDLEY_PUBLIC)
1970     #undef JSON_HEDLEY_PUBLIC
1971 #endif
1972 #if defined(JSON_HEDLEY_IMPORT)
1973     #undef JSON_HEDLEY_IMPORT
1974 #endif
1975 #if defined(_WIN32) || defined(__CYGWIN__)
1976 #  define JSON_HEDLEY_PRIVATE
1977 #  define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
1978 #  define JSON_HEDLEY_IMPORT   __declspec(dllimport)
1979 #else
1980 #  if \ 
1981     JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ 
1982     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 
1983     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 
1984     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
1985     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
1986     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 
1987     ( \ 
1988       defined(__TI_EABI__) && \ 
1989       ( \ 
1990         (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 
1991         JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ 
1992       ) \ 
1993     ) || \ 
1994     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1995 #    define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1996 #    define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
1997 #  else
1998 #    define JSON_HEDLEY_PRIVATE
1999 #    define JSON_HEDLEY_PUBLIC
2000 #  endif
2001 #  define JSON_HEDLEY_IMPORT    extern
2002 #endif
2003 
2004 #if defined(JSON_HEDLEY_NO_THROW)
2005     #undef JSON_HEDLEY_NO_THROW
2006 #endif
2007 #if \ 
2008     JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ 
2009     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 
2010     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
2011     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2012     #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2013 #elif \ 
2014     JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ 
2015     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 
2016     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2017     #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2018 #else
2019     #define JSON_HEDLEY_NO_THROW
2020 #endif
2021 
2022 #if defined(JSON_HEDLEY_FALL_THROUGH)
2023     #undef JSON_HEDLEY_FALL_THROUGH
2024 #endif
2025 #if \ 
2026     JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ 
2027     JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ 
2028     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2029     #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2030 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2031     #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2032 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2033     #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2034 #elif defined(__fallthrough) /* SAL */
2035     #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2036 #else
2037     #define JSON_HEDLEY_FALL_THROUGH
2038 #endif
2039 
2040 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2041     #undef JSON_HEDLEY_RETURNS_NON_NULL
2042 #endif
2043 #if \ 
2044     JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ 
2045     JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 
2046     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2047     #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2048 #elif defined(_Ret_notnull_) /* SAL */
2049     #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2050 #else
2051     #define JSON_HEDLEY_RETURNS_NON_NULL
2052 #endif
2053 
2054 #if defined(JSON_HEDLEY_ARRAY_PARAM)
2055     #undef JSON_HEDLEY_ARRAY_PARAM
2056 #endif
2057 #if \ 
2058     defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ 
2059     !defined(__STDC_NO_VLA__) && \ 
2060     !defined(__cplusplus) && \ 
2061     !defined(JSON_HEDLEY_PGI_VERSION) && \ 
2062     !defined(JSON_HEDLEY_TINYC_VERSION)
2063     #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2064 #else
2065     #define JSON_HEDLEY_ARRAY_PARAM(name)
2066 #endif
2067 
2068 #if defined(JSON_HEDLEY_IS_CONSTANT)
2069     #undef JSON_HEDLEY_IS_CONSTANT
2070 #endif
2071 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2072     #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2073 #endif
2074 /* JSON_HEDLEY_IS_CONSTEXPR_ is for 
2075    HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
2076 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2077     #undef JSON_HEDLEY_IS_CONSTEXPR_
2078 #endif
2079 #if \ 
2080     JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ 
2081     JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 
2082     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
2083     JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ 
2084     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 
2085     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 
2086     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 
2087     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ 
2088     JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 
2089     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2090     #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2091 #endif
2092 #if !defined(__cplusplus)
2093 #  if \ 
2094        JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ 
2095        JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 
2096        JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
2097        JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 
2098        JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 
2099        JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 
2100        JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2101 #if defined(__INTPTR_TYPE__)
2102     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2103 #else
2104     #include <stdint.h>
2105     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2106 #endif
2107 #  elif \ 
2108        ( \ 
2109           defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ 
2110           !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ 
2111           !defined(JSON_HEDLEY_PGI_VERSION) && \ 
2112           !defined(JSON_HEDLEY_IAR_VERSION)) || \ 
2113        (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 
2114        JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 
2115        JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ 
2116        JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 
2117        JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2118 #if defined(__INTPTR_TYPE__)
2119     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2120 #else
2121     #include <stdint.h>
2122     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2123 #endif
2124 #  elif \ 
2125        defined(JSON_HEDLEY_GCC_VERSION) || \ 
2126        defined(JSON_HEDLEY_INTEL_VERSION) || \ 
2127        defined(JSON_HEDLEY_TINYC_VERSION) || \ 
2128        defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ 
2129        JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ 
2130        defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ 
2131        defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ 
2132        defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ 
2133        defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ 
2134        defined(__clang__)
2135 #    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ 
2136         sizeof(void) != \ 
2137         sizeof(*( \ 
2138                   1 ? \ 
2139                   ((void*) ((expr) * 0L) ) : \ 
2140 ((struct { char v[sizeof(void) * 2]; } *) 1) \ 
2141                 ) \ 
2142               ) \ 
2143                                             )
2144 #  endif
2145 #endif
2146 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2147     #if !defined(JSON_HEDLEY_IS_CONSTANT)
2148         #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2149     #endif
2150     #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2151 #else
2152     #if !defined(JSON_HEDLEY_IS_CONSTANT)
2153         #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2154     #endif
2155     #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2156 #endif
2157 
2158 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2159     #undef JSON_HEDLEY_BEGIN_C_DECLS
2160 #endif
2161 #if defined(JSON_HEDLEY_END_C_DECLS)
2162     #undef JSON_HEDLEY_END_C_DECLS
2163 #endif
2164 #if defined(JSON_HEDLEY_C_DECL)
2165     #undef JSON_HEDLEY_C_DECL
2166 #endif
2167 #if defined(__cplusplus)
2168     #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2169     #define JSON_HEDLEY_END_C_DECLS }
2170     #define JSON_HEDLEY_C_DECL extern "C"
2171 #else
2172     #define JSON_HEDLEY_BEGIN_C_DECLS
2173     #define JSON_HEDLEY_END_C_DECLS
2174     #define JSON_HEDLEY_C_DECL
2175 #endif
2176 
2177 #if defined(JSON_HEDLEY_STATIC_ASSERT)
2178     #undef JSON_HEDLEY_STATIC_ASSERT
2179 #endif
2180 #if \ 
2181   !defined(__cplusplus) && ( \ 
2182       (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ 
2183       (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 
2184       JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ 
2185       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 
2186       defined(_Static_assert) \ 
2187     )
2188 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2189 #elif \ 
2190   (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 
2191   JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ 
2192   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2193 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2194 #else
2195 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2196 #endif
2197 
2198 #if defined(JSON_HEDLEY_NULL)
2199     #undef JSON_HEDLEY_NULL
2200 #endif
2201 #if defined(__cplusplus)
2202     #if __cplusplus >= 201103L
2203         #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2204     #elif defined(NULL)
2205         #define JSON_HEDLEY_NULL NULL
2206     #else
2207         #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2208     #endif
2209 #elif defined(NULL)
2210     #define JSON_HEDLEY_NULL NULL
2211 #else
2212     #define JSON_HEDLEY_NULL ((void*) 0)
2213 #endif
2214 
2215 #if defined(JSON_HEDLEY_MESSAGE)
2216     #undef JSON_HEDLEY_MESSAGE
2217 #endif
2218 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2219 #  define JSON_HEDLEY_MESSAGE(msg) \ 
2220     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
2221     JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 
2222     JSON_HEDLEY_PRAGMA(message msg) \ 
2223     JSON_HEDLEY_DIAGNOSTIC_POP
2224 #elif \ 
2225   JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ 
2226   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2227 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2228 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2229 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2230 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2231 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2232 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2233 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2234 #else
2235 #  define JSON_HEDLEY_MESSAGE(msg)
2236 #endif
2237 
2238 #if defined(JSON_HEDLEY_WARNING)
2239     #undef JSON_HEDLEY_WARNING
2240 #endif
2241 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2242 #  define JSON_HEDLEY_WARNING(msg) \ 
2243     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
2244     JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 
2245     JSON_HEDLEY_PRAGMA(clang warning msg) \ 
2246     JSON_HEDLEY_DIAGNOSTIC_POP
2247 #elif \ 
2248   JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ 
2249   JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 
2250   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2251 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2252 #elif \ 
2253   JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 
2254   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2255 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2256 #else
2257 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2258 #endif
2259 
2260 #if defined(JSON_HEDLEY_REQUIRE)
2261     #undef JSON_HEDLEY_REQUIRE
2262 #endif
2263 #if defined(JSON_HEDLEY_REQUIRE_MSG)
2264     #undef JSON_HEDLEY_REQUIRE_MSG
2265 #endif
2266 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2267 #  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2268 #    define JSON_HEDLEY_REQUIRE(expr) \ 
2269     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
2270     _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 
2271     __attribute__((diagnose_if(!(expr), #expr, "error"))) \ 
2272     JSON_HEDLEY_DIAGNOSTIC_POP
2273 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ 
2274     JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
2275     _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 
2276     __attribute__((diagnose_if(!(expr), msg, "error"))) \ 
2277     JSON_HEDLEY_DIAGNOSTIC_POP
2278 #  else
2279 #    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2280 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2281 #  endif
2282 #else
2283 #  define JSON_HEDLEY_REQUIRE(expr)
2284 #  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2285 #endif
2286 
2287 #if defined(JSON_HEDLEY_FLAGS)
2288     #undef JSON_HEDLEY_FLAGS
2289 #endif
2290 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2291     #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2292 #else
2293     #define JSON_HEDLEY_FLAGS
2294 #endif
2295 
2296 #if defined(JSON_HEDLEY_FLAGS_CAST)
2297     #undef JSON_HEDLEY_FLAGS_CAST
2298 #endif
2299 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2300 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ 
2301         JSON_HEDLEY_DIAGNOSTIC_PUSH \ 
2302         _Pragma("warning(disable:188)") \ 
2303         ((T) (expr)); \ 
2304         JSON_HEDLEY_DIAGNOSTIC_POP \ 
2305     }))
2306 #else
2307 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2308 #endif
2309 
2310 #if defined(JSON_HEDLEY_EMPTY_BASES)
2311     #undef JSON_HEDLEY_EMPTY_BASES
2312 #endif
2313 #if \ 
2314     (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ 
2315     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2316     #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2317 #else
2318     #define JSON_HEDLEY_EMPTY_BASES
2319 #endif
2320 
2321 /* Remaining macros are deprecated. */
2322 
2323 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2324     #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2325 #endif
2326 #if defined(__clang__)
2327     #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2328 #else
2329     #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2330 #endif
2331 
2332 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2333     #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2334 #endif
2335 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2336 
2337 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2338     #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2339 #endif
2340 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2341 
2342 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2343     #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2344 #endif
2345 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2346 
2347 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2348     #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2349 #endif
2350 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2351 
2352 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2353     #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2354 #endif
2355 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2356 
2357 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2358     #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2359 #endif
2360 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2361 
2362 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2363     #undef JSON_HEDLEY_CLANG_HAS_WARNING
2364 #endif
2365 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2366 
2367 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2368 
2369 
2370 // This file contains all internal macro definitions (except those affecting ABI)
2371 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2372 
2373 // #include <nlohmann/detail/abi_macros.hpp>
2374 
2375 
2376 // exclude unsupported compilers
2377 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2378     #if defined(__clang__)
2379         #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2380             #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2381         #endif
2382     #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2383         #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2384             #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2385         #endif
2386     #endif
2387 #endif
2388 
2389 // C++ language standard detection
2390 // if the user manually specified the used c++ version this is skipped
2391 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2392     #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2393         #define JSON_HAS_CPP_20
2394         #define JSON_HAS_CPP_17
2395         #define JSON_HAS_CPP_14
2396     #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2397         #define JSON_HAS_CPP_17
2398         #define JSON_HAS_CPP_14
2399     #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2400         #define JSON_HAS_CPP_14
2401     #endif
2402     // the cpp 11 flag is always specified because it is the minimal required version
2403     #define JSON_HAS_CPP_11
2404 #endif
2405 
2406 #ifdef __has_include
2407     #if __has_include(<version>)
2408         #include <version>
2409     #endif
2410 #endif
2411 
2412 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2413     #ifdef JSON_HAS_CPP_17
2414         #if defined(__cpp_lib_filesystem)
2415             #define JSON_HAS_FILESYSTEM 1
2416         #elif defined(__cpp_lib_experimental_filesystem)
2417             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2418         #elif !defined(__has_include)
2419             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2420         #elif __has_include(<filesystem>)
2421             #define JSON_HAS_FILESYSTEM 1
2422         #elif __has_include(<experimental/filesystem>)
2423             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2424         #endif
2425 
2426         // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2427         #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2428             #undef JSON_HAS_FILESYSTEM
2429             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2430         #endif
2431 
2432         // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2433         #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2434             #undef JSON_HAS_FILESYSTEM
2435             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2436         #endif
2437 
2438         // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2439         #if defined(__clang_major__) && __clang_major__ < 7
2440             #undef JSON_HAS_FILESYSTEM
2441             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2442         #endif
2443 
2444         // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2445         #if defined(_MSC_VER) && _MSC_VER < 1914
2446             #undef JSON_HAS_FILESYSTEM
2447             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2448         #endif
2449 
2450         // no filesystem support before iOS 13
2451         #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2452             #undef JSON_HAS_FILESYSTEM
2453             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2454         #endif
2455 
2456         // no filesystem support before macOS Catalina
2457         #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2458             #undef JSON_HAS_FILESYSTEM
2459             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2460         #endif
2461     #endif
2462 #endif
2463 
2464 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2465     #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2466 #endif
2467 
2468 #ifndef JSON_HAS_FILESYSTEM
2469     #define JSON_HAS_FILESYSTEM 0
2470 #endif
2471 
2472 #ifndef JSON_HAS_THREE_WAY_COMPARISON
2473     #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ 
2474         && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2475         #define JSON_HAS_THREE_WAY_COMPARISON 1
2476     #else
2477         #define JSON_HAS_THREE_WAY_COMPARISON 0
2478     #endif
2479 #endif
2480 
2481 #ifndef JSON_HAS_RANGES
2482     // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2483     #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2484         #define JSON_HAS_RANGES 0
2485     #elif defined(__cpp_lib_ranges)
2486         #define JSON_HAS_RANGES 1
2487     #else
2488         #define JSON_HAS_RANGES 0
2489     #endif
2490 #endif
2491 
2492 #ifndef JSON_HAS_STATIC_RTTI
2493     #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2494         #define JSON_HAS_STATIC_RTTI 1
2495     #else
2496         #define JSON_HAS_STATIC_RTTI 0
2497     #endif
2498 #endif
2499 
2500 #ifdef JSON_HAS_CPP_17
2501     #define JSON_INLINE_VARIABLE inline
2502 #else
2503     #define JSON_INLINE_VARIABLE
2504 #endif
2505 
2506 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2507     #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2508 #else
2509     #define JSON_NO_UNIQUE_ADDRESS
2510 #endif
2511 
2512 // disable documentation warnings on clang
2513 #if defined(__clang__)
2514     #pragma clang diagnostic push
2515     #pragma clang diagnostic ignored "-Wdocumentation"
2516     #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2517 #endif
2518 
2519 // allow disabling exceptions
2520 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2521     #define JSON_THROW(exception) throw exception
2522     #define JSON_TRY try
2523     #define JSON_CATCH(exception) catch(exception)
2524     #define JSON_INTERNAL_CATCH(exception) catch(exception)
2525 #else
2526     #include <cstdlib>
2527     #define JSON_THROW(exception) std::abort()
2528     #define JSON_TRY if(true)
2529     #define JSON_CATCH(exception) if(false)
2530     #define JSON_INTERNAL_CATCH(exception) if(false)
2531 #endif
2532 
2533 // override exception macros
2534 #if defined(JSON_THROW_USER)
2535     #undef JSON_THROW
2536     #define JSON_THROW JSON_THROW_USER
2537 #endif
2538 #if defined(JSON_TRY_USER)
2539     #undef JSON_TRY
2540     #define JSON_TRY JSON_TRY_USER
2541 #endif
2542 #if defined(JSON_CATCH_USER)
2543     #undef JSON_CATCH
2544     #define JSON_CATCH JSON_CATCH_USER
2545     #undef JSON_INTERNAL_CATCH
2546     #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2547 #endif
2548 #if defined(JSON_INTERNAL_CATCH_USER)
2549     #undef JSON_INTERNAL_CATCH
2550     #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2551 #endif
2552 
2553 // allow overriding assert
2554 #if !defined(JSON_ASSERT)
2555     #include <cassert> // assert
2556     #define JSON_ASSERT(x) assert(x)
2557 #endif
2558 
2559 // allow to access some private functions (needed by the test suite)
2560 #if defined(JSON_TESTS_PRIVATE)
2561     #define JSON_PRIVATE_UNLESS_TESTED public
2562 #else
2563     #define JSON_PRIVATE_UNLESS_TESTED private
2564 #endif
2565 
2566 /*! 
2567 @brief macro to briefly define a mapping between an enum and JSON 
2568 @def NLOHMANN_JSON_SERIALIZE_ENUM 
2569 @since version 3.4.0 
2570 */
2571 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \ 
2572     template<typename BasicJsonType>                                                            \ 
2573     inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \ 
2574     {                                                                                           \ 
2575         /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */                                \ 
2576         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \ 
2577         /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */       \ 
2578         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \ 
2579         auto it = std::find_if(std::begin(m), std::end(m),                                      \ 
2580                                [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \ 
2581         {                                                                                       \ 
2582             return ej_pair.first == e;                                                          \ 
2583         });                                                                                     \ 
2584         j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \ 
2585     }                                                                                           \ 
2586     template<typename BasicJsonType>                                                            \ 
2587     inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \ 
2588     {                                                                                           \ 
2589         /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */                                \ 
2590         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \ 
2591         /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */       \ 
2592         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \ 
2593         auto it = std::find_if(std::begin(m), std::end(m),                                      \ 
2594                                [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ 
2595         {                                                                                       \ 
2596             return ej_pair.second == j;                                                         \ 
2597         });                                                                                     \ 
2598         e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \ 
2599     }
2600 
2601 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2602 // may be removed in the future once the class is split.
2603 
2604 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \ 
2605     template<template<typename, typename, typename...> class ObjectType,   \ 
2606              template<typename, typename...> class ArrayType,              \ 
2607              class StringType, class BooleanType, class NumberIntegerType, \ 
2608              class NumberUnsignedType, class NumberFloatType,              \ 
2609              template<typename> class AllocatorType,                       \ 
2610              template<typename, typename = void> class JSONSerializer,     \ 
2611              class BinaryType,                                             \ 
2612              class CustomBaseClass>
2613 
2614 #define NLOHMANN_BASIC_JSON_TPL                                            \ 
2615     basic_json<ObjectType, ArrayType, StringType, BooleanType,             \ 
2616     NumberIntegerType, NumberUnsignedType, NumberFloatType,                \ 
2617     AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2618 
2619 // Macros to simplify conversion from/to types
2620 
2621 #define NLOHMANN_JSON_EXPAND( x ) x
2622 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2623 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ 
2624         NLOHMANN_JSON_PASTE64, \ 
2625         NLOHMANN_JSON_PASTE63, \ 
2626         NLOHMANN_JSON_PASTE62, \ 
2627         NLOHMANN_JSON_PASTE61, \ 
2628         NLOHMANN_JSON_PASTE60, \ 
2629         NLOHMANN_JSON_PASTE59, \ 
2630         NLOHMANN_JSON_PASTE58, \ 
2631         NLOHMANN_JSON_PASTE57, \ 
2632         NLOHMANN_JSON_PASTE56, \ 
2633         NLOHMANN_JSON_PASTE55, \ 
2634         NLOHMANN_JSON_PASTE54, \ 
2635         NLOHMANN_JSON_PASTE53, \ 
2636         NLOHMANN_JSON_PASTE52, \ 
2637         NLOHMANN_JSON_PASTE51, \ 
2638         NLOHMANN_JSON_PASTE50, \ 
2639         NLOHMANN_JSON_PASTE49, \ 
2640         NLOHMANN_JSON_PASTE48, \ 
2641         NLOHMANN_JSON_PASTE47, \ 
2642         NLOHMANN_JSON_PASTE46, \ 
2643         NLOHMANN_JSON_PASTE45, \ 
2644         NLOHMANN_JSON_PASTE44, \ 
2645         NLOHMANN_JSON_PASTE43, \ 
2646         NLOHMANN_JSON_PASTE42, \ 
2647         NLOHMANN_JSON_PASTE41, \ 
2648         NLOHMANN_JSON_PASTE40, \ 
2649         NLOHMANN_JSON_PASTE39, \ 
2650         NLOHMANN_JSON_PASTE38, \ 
2651         NLOHMANN_JSON_PASTE37, \ 
2652         NLOHMANN_JSON_PASTE36, \ 
2653         NLOHMANN_JSON_PASTE35, \ 
2654         NLOHMANN_JSON_PASTE34, \ 
2655         NLOHMANN_JSON_PASTE33, \ 
2656         NLOHMANN_JSON_PASTE32, \ 
2657         NLOHMANN_JSON_PASTE31, \ 
2658         NLOHMANN_JSON_PASTE30, \ 
2659         NLOHMANN_JSON_PASTE29, \ 
2660         NLOHMANN_JSON_PASTE28, \ 
2661         NLOHMANN_JSON_PASTE27, \ 
2662         NLOHMANN_JSON_PASTE26, \ 
2663         NLOHMANN_JSON_PASTE25, \ 
2664         NLOHMANN_JSON_PASTE24, \ 
2665         NLOHMANN_JSON_PASTE23, \ 
2666         NLOHMANN_JSON_PASTE22, \ 
2667         NLOHMANN_JSON_PASTE21, \ 
2668         NLOHMANN_JSON_PASTE20, \ 
2669         NLOHMANN_JSON_PASTE19, \ 
2670         NLOHMANN_JSON_PASTE18, \ 
2671         NLOHMANN_JSON_PASTE17, \ 
2672         NLOHMANN_JSON_PASTE16, \ 
2673         NLOHMANN_JSON_PASTE15, \ 
2674         NLOHMANN_JSON_PASTE14, \ 
2675         NLOHMANN_JSON_PASTE13, \ 
2676         NLOHMANN_JSON_PASTE12, \ 
2677         NLOHMANN_JSON_PASTE11, \ 
2678         NLOHMANN_JSON_PASTE10, \ 
2679         NLOHMANN_JSON_PASTE9, \ 
2680         NLOHMANN_JSON_PASTE8, \ 
2681         NLOHMANN_JSON_PASTE7, \ 
2682         NLOHMANN_JSON_PASTE6, \ 
2683         NLOHMANN_JSON_PASTE5, \ 
2684         NLOHMANN_JSON_PASTE4, \ 
2685         NLOHMANN_JSON_PASTE3, \ 
2686         NLOHMANN_JSON_PASTE2, \ 
2687         NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2688 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2689 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2690 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2691 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2692 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2693 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2694 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2695 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2696 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2697 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2698 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2699 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2700 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2701 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2702 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2703 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2704 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2705 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2706 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2707 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2708 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2709 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2710 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2711 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2712 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2713 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2714 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2715 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2716 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2717 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2718 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2719 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2720 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2721 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2722 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2723 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2724 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2725 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2726 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2727 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2728 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2729 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2730 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2731 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2732 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2733 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2734 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2735 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2736 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2737 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2738 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2739 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2740 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2741 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2742 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2743 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2744 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2745 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2746 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2747 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2748 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2749 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2750 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2751 
2752 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2753 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2754 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2755 
2756 /*! 
2757 @brief macro 
2758 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE 
2759 @since version 3.9.0 
2760 */
2761 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \ 
2762     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2763     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2764 
2765 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \ 
2766     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2767     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2768 
2769 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...)  \ 
2770     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2771 
2772 /*! 
2773 @brief macro 
2774 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE 
2775 @since version 3.9.0 
2776 */
2777 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \ 
2778     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2779     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2780 
2781 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...)  \ 
2782     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2783 
2784 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...)  \ 
2785     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2786     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2787 
2788 /*! 
2789 @brief macro 
2790 @def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE 
2791 @since version 3.11.x 
2792 */
2793 #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...)  \ 
2794     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2795     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2796 
2797 #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...)  \ 
2798     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2799     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2800 
2801 /*! 
2802 @brief macro 
2803 @def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE 
2804 @since version 3.11.x 
2805 */
2806 #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...)  \ 
2807     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2808     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2809 
2810 #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...)  \ 
2811     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 
2812     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2813 
2814 // inspired from https://stackoverflow.com/a/26745591
2815 // allows to call any std function as if (e.g. with begin):
2816 // using std::begin; begin(x);
2817 //
2818 // it allows using the detected idiom to retrieve the return type
2819 // of such an expression
2820 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \ 
2821     namespace detail {                                                            \ 
2822     using std::std_name;                                                          \ 
2823     \ 
2824     template<typename... T>                                                       \ 
2825     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \ 
2826     }                                                                             \ 
2827     \ 
2828     namespace detail2 {                                                           \ 
2829     struct std_name##_tag                                                         \ 
2830     {                                                                             \ 
2831     };                                                                            \ 
2832     \ 
2833     template<typename... T>                                                       \ 
2834     std_name##_tag std_name(T&&...);                                              \ 
2835     \ 
2836     template<typename... T>                                                       \ 
2837     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \ 
2838     \ 
2839     template<typename... T>                                                       \ 
2840     struct would_call_std_##std_name                                              \ 
2841     {                                                                             \ 
2842         static constexpr auto const value = ::nlohmann::detail::                  \ 
2843                                             is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \ 
2844     };                                                                            \ 
2845     } /* namespace detail2 */ \ 
2846     \ 
2847     template<typename... T>                                                       \ 
2848     struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \ 
2849     {                                                                             \ 
2850     }
2851 
2852 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2853     #define JSON_USE_IMPLICIT_CONVERSIONS 1
2854 #endif
2855 
2856 #if JSON_USE_IMPLICIT_CONVERSIONS
2857     #define JSON_EXPLICIT
2858 #else
2859     #define JSON_EXPLICIT explicit
2860 #endif
2861 
2862 #ifndef JSON_DISABLE_ENUM_SERIALIZATION
2863     #define JSON_DISABLE_ENUM_SERIALIZATION 0
2864 #endif
2865 
2866 #ifndef JSON_USE_GLOBAL_UDLS
2867     #define JSON_USE_GLOBAL_UDLS 1
2868 #endif
2869 
2870 #if JSON_HAS_THREE_WAY_COMPARISON
2871     #include <compare> // partial_ordering
2872 #endif
2873 
2874 NLOHMANN_JSON_NAMESPACE_BEGIN
2875 namespace detail
2876 {
2877 
2878 ///////////////////////////
2879 // JSON type enumeration //
2880 ///////////////////////////
2881 
2882 /*! 
2883 @brief the JSON type enumeration 
2884  
2885 This enumeration collects the different JSON types. It is internally used to 
2886 distinguish the stored values, and the functions @ref basic_json::is_null(), 
2887 @ref basic_json::is_object(), @ref basic_json::is_array(), 
2888 @ref basic_json::is_string(), @ref basic_json::is_boolean(), 
2889 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(), 
2890 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), 
2891 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and 
2892 @ref basic_json::is_structured() rely on it. 
2893  
2894 @note There are three enumeration entries (number_integer, number_unsigned, and 
2895 number_float), because the library distinguishes these three types for numbers: 
2896 @ref basic_json::number_unsigned_t is used for unsigned integers, 
2897 @ref basic_json::number_integer_t is used for signed integers, and 
2898 @ref basic_json::number_float_t is used for floating-point numbers or to 
2899 approximate integers which do not fit in the limits of their respective type. 
2900  
2901 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON 
2902 value with the default value for a given type 
2903  
2904 @since version 1.0.0 
2905 */
2906 enum class value_t : std::uint8_t
2907 {
2908     null,             ///< null value
2909     object,           ///< object (unordered set of name/value pairs)
2910     array,            ///< array (ordered collection of values)
2911     string,           ///< string value
2912     boolean,          ///< boolean value
2913     number_integer,   ///< number value (signed integer)
2914     number_unsigned,  ///< number value (unsigned integer)
2915     number_float,     ///< number value (floating-point)
2916     binary,           ///< binary array (ordered collection of bytes)
2917     discarded         ///< discarded by the parser callback function
2918 };
2919 
2920 /*! 
2921 @brief comparison operator for JSON types 
2922  
2923 Returns an ordering that is similar to Python: 
2924 - order: null < boolean < number < object < array < string < binary 
2925 - furthermore, each type is not smaller than itself 
2926 - discarded values are not comparable 
2927 - binary is represented as a b"" string in python and directly comparable to a 
2928   string; however, making a binary array directly comparable with a string would 
2929   be surprising behavior in a JSON file. 
2930  
2931 @since version 1.0.0 
2932 */
2933 #if JSON_HAS_THREE_WAY_COMPARISON
2934     inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2935 #else
2936     inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2937 #endif
2938 {
2939     static constexpr std::array<std::uint8_t, 9> order = {{
2940             0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2941             1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2942             6 /* binary */
2943         }
2944     };
2945 
2946     const auto l_index = static_cast<std::size_t>(lhs);
2947     const auto r_index = static_cast<std::size_t>(rhs);
2948 #if JSON_HAS_THREE_WAY_COMPARISON
2949     if (l_index < order.size() && r_index < order.size())
2950     {
2951         return order[l_index] <=> order[r_index]; // *NOPAD*
2952     }
2953     return std::partial_ordering::unordered;
2954 #else
2955     return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2956 #endif
2957 }
2958 
2959 // GCC selects the built-in operator< over an operator rewritten from
2960 // a user-defined spaceship operator
2961 // Clang, MSVC, and ICC select the rewritten candidate
2962 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2963 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2964 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2965 {
2966     return std::is_lt(lhs <=> rhs); // *NOPAD*
2967 }
2968 #endif
2969 
2970 }  // namespace detail
2971 NLOHMANN_JSON_NAMESPACE_END
2972 
2973 // #include <nlohmann/detail/string_escape.hpp>
2974 //     __ _____ _____ _____
2975 //  __|  |   __|     |   | |  JSON for Modern C++
2976 // |  |  |__   |  |  | | | |  version 3.11.3
2977 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
2978 //
2979 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
2980 // SPDX-License-Identifier: MIT
2981 
2982 
2983 
2984 // #include <nlohmann/detail/abi_macros.hpp>
2985 
2986 
2987 NLOHMANN_JSON_NAMESPACE_BEGIN
2988 namespace detail
2989 {
2990 
2991 /*! 
2992 @brief replace all occurrences of a substring by another string 
2993  
2994 @param[in,out] s  the string to manipulate; changed so that all 
2995                occurrences of @a f are replaced with @a t 
2996 @param[in]     f  the substring to replace with @a t 
2997 @param[in]     t  the string to replace @a f 
2998  
2999 @pre The search string @a f must not be empty. **This precondition is 
3000 enforced with an assertion.** 
3001  
3002 @since version 2.0.0 
3003 */
3004 template<typename StringType>
3005 inline void replace_substring(StringType& s, const StringType& f,
3006                               const StringType& t)
3007 {
3008     JSON_ASSERT(!f.empty());
3009     for (auto pos = s.find(f);                // find first occurrence of f
3010             pos != StringType::npos;          // make sure f was found
3011             s.replace(pos, f.size(), t),      // replace with t, and
3012             pos = s.find(f, pos + t.size()))  // find next occurrence of f
3013     {}
3014 }
3015 
3016 /*! 
3017  * @brief string escaping as described in RFC 6901 (Sect. 4) 
3018  * @param[in] s string to escape 
3019  * @return    escaped string 
3020  * 
3021  * Note the order of escaping "~" to "~0" and "/" to "~1" is important. 
3022  */
3023 template<typename StringType>
3024 inline StringType escape(StringType s)
3025 {
3026     replace_substring(s, StringType{"~"}, StringType{"~0"});
3027     replace_substring(s, StringType{"/"}, StringType{"~1"});
3028     return s;
3029 }
3030 
3031 /*! 
3032  * @brief string unescaping as described in RFC 6901 (Sect. 4) 
3033  * @param[in] s string to unescape 
3034  * @return    unescaped string 
3035  * 
3036  * Note the order of escaping "~1" to "/" and "~0" to "~" is important. 
3037  */
3038 template<typename StringType>
3039 static void unescape(StringType& s)
3040 {
3041     replace_substring(s, StringType{"~1"}, StringType{"/"});
3042     replace_substring(s, StringType{"~0"}, StringType{"~"});
3043 }
3044 
3045 }  // namespace detail
3046 NLOHMANN_JSON_NAMESPACE_END
3047 
3048 // #include <nlohmann/detail/input/position_t.hpp>
3049 //     __ _____ _____ _____
3050 //  __|  |   __|     |   | |  JSON for Modern C++
3051 // |  |  |__   |  |  | | | |  version 3.11.3
3052 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3053 //
3054 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3055 // SPDX-License-Identifier: MIT
3056 
3057 
3058 
3059 #include <cstddef> // size_t
3060 
3061 // #include <nlohmann/detail/abi_macros.hpp>
3062 
3063 
3064 NLOHMANN_JSON_NAMESPACE_BEGIN
3065 namespace detail
3066 {
3067 
3068 /// struct to capture the start position of the current token
3069 struct position_t
3070 {
3071     /// the total number of characters read
3072     std::size_t chars_read_total = 0;
3073     /// the number of characters read in the current line
3074     std::size_t chars_read_current_line = 0;
3075     /// the number of lines read
3076     std::size_t lines_read = 0;
3077 
3078     /// conversion to size_t to preserve SAX interface
3079     constexpr operator size_t() const
3080     {
3081         return chars_read_total;
3082     }
3083 };
3084 
3085 }  // namespace detail
3086 NLOHMANN_JSON_NAMESPACE_END
3087 
3088 // #include <nlohmann/detail/macro_scope.hpp>
3089 
3090 // #include <nlohmann/detail/meta/cpp_future.hpp>
3091 //     __ _____ _____ _____
3092 //  __|  |   __|     |   | |  JSON for Modern C++
3093 // |  |  |__   |  |  | | | |  version 3.11.3
3094 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3095 //
3096 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3097 // SPDX-FileCopyrightText: 2018 The Abseil Authors
3098 // SPDX-License-Identifier: MIT
3099 
3100 
3101 
3102 #include <array> // array
3103 #include <cstddef> // size_t
3104 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3105 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
3106 
3107 // #include <nlohmann/detail/macro_scope.hpp>
3108 
3109 
3110 NLOHMANN_JSON_NAMESPACE_BEGIN
3111 namespace detail
3112 {
3113 
3114 template<typename T>
3115 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3116 
3117 #ifdef JSON_HAS_CPP_14
3118 
3119 // the following utilities are natively available in C++14
3120 using std::enable_if_t;
3121 using std::index_sequence;
3122 using std::make_index_sequence;
3123 using std::index_sequence_for;
3124 
3125 #else
3126 
3127 // alias templates to reduce boilerplate
3128 template<bool B, typename T = void>
3129 using enable_if_t = typename std::enable_if<B, T>::type;
3130 
3131 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3132 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3133 
3134 //// START OF CODE FROM GOOGLE ABSEIL
3135 
3136 // integer_sequence
3137 //
3138 // Class template representing a compile-time integer sequence. An instantiation
3139 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3140 // type through its template arguments (which is a common need when
3141 // working with C++11 variadic templates). `absl::integer_sequence` is designed
3142 // to be a drop-in replacement for C++14's `std::integer_sequence`.
3143 //
3144 // Example:
3145 //
3146 //   template< class T, T... Ints >
3147 //   void user_function(integer_sequence<T, Ints...>);
3148 //
3149 //   int main()
3150 //   {
3151 //     // user_function's `T` will be deduced to `int` and `Ints...`
3152 //     // will be deduced to `0, 1, 2, 3, 4`.
3153 //     user_function(make_integer_sequence<int, 5>());
3154 //   }
3155 template <typename T, T... Ints>
3156 struct integer_sequence
3157 {
3158     using value_type = T;
3159     static constexpr std::size_t size() noexcept
3160     {
3161         return sizeof...(Ints);
3162     }
3163 };
3164 
3165 // index_sequence
3166 //
3167 // A helper template for an `integer_sequence` of `size_t`,
3168 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3169 // `std::index_sequence`.
3170 template <size_t... Ints>
3171 using index_sequence = integer_sequence<size_t, Ints...>;
3172 
3173 namespace utility_internal
3174 {
3175 
3176 template <typename Seq, size_t SeqSize, size_t Rem>
3177 struct Extend;
3178 
3179 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3180 template <typename T, T... Ints, size_t SeqSize>
3181 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3182 {
3183     using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3184 };
3185 
3186 template <typename T, T... Ints, size_t SeqSize>
3187 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3188 {
3189     using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3190 };
3191 
3192 // Recursion helper for 'make_integer_sequence<T, N>'.
3193 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3194 template <typename T, size_t N>
3195 struct Gen
3196 {
3197     using type =
3198         typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3199 };
3200 
3201 template <typename T>
3202 struct Gen<T, 0>
3203 {
3204     using type = integer_sequence<T>;
3205 };
3206 
3207 }  // namespace utility_internal
3208 
3209 // Compile-time sequences of integers
3210 
3211 // make_integer_sequence
3212 //
3213 // This template alias is equivalent to
3214 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3215 // replacement for C++14's `std::make_integer_sequence`.
3216 template <typename T, T N>
3217 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3218 
3219 // make_index_sequence
3220 //
3221 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3222 // and is designed to be a drop-in replacement for C++14's
3223 // `std::make_index_sequence`.
3224 template <size_t N>
3225 using make_index_sequence = make_integer_sequence<size_t, N>;
3226 
3227 // index_sequence_for
3228 //
3229 // Converts a typename pack into an index sequence of the same length, and
3230 // is designed to be a drop-in replacement for C++14's
3231 // `std::index_sequence_for()`
3232 template <typename... Ts>
3233 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3234 
3235 //// END OF CODE FROM GOOGLE ABSEIL
3236 
3237 #endif
3238 
3239 // dispatch utility (taken from ranges-v3)
3240 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3241 template<> struct priority_tag<0> {};
3242 
3243 // taken from ranges-v3
3244 template<typename T>
3245 struct static_const
3246 {
3247     static JSON_INLINE_VARIABLE constexpr T value{};
3248 };
3249 
3250 #ifndef JSON_HAS_CPP_17
3251     template<typename T>
3252     constexpr T static_const<T>::value;
3253 #endif
3254 
3255 template<typename T, typename... Args>
3256 constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3257 {
3258     return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3259 }
3260 
3261 }  // namespace detail
3262 NLOHMANN_JSON_NAMESPACE_END
3263 
3264 // #include <nlohmann/detail/meta/type_traits.hpp>
3265 //     __ _____ _____ _____
3266 //  __|  |   __|     |   | |  JSON for Modern C++
3267 // |  |  |__   |  |  | | | |  version 3.11.3
3268 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3269 //
3270 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3271 // SPDX-License-Identifier: MIT
3272 
3273 
3274 
3275 #include <limits> // numeric_limits
3276 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3277 #include <utility> // declval
3278 #include <tuple> // tuple
3279 #include <string> // char_traits
3280 
3281 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
3282 //     __ _____ _____ _____
3283 //  __|  |   __|     |   | |  JSON for Modern C++
3284 // |  |  |__   |  |  | | | |  version 3.11.3
3285 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3286 //
3287 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3288 // SPDX-License-Identifier: MIT
3289 
3290 
3291 
3292 #include <iterator> // random_access_iterator_tag
3293 
3294 // #include <nlohmann/detail/abi_macros.hpp>
3295 
3296 // #include <nlohmann/detail/meta/void_t.hpp>
3297 
3298 // #include <nlohmann/detail/meta/cpp_future.hpp>
3299 
3300 
3301 NLOHMANN_JSON_NAMESPACE_BEGIN
3302 namespace detail
3303 {
3304 
3305 template<typename It, typename = void>
3306 struct iterator_types {};
3307 
3308 template<typename It>
3309 struct iterator_types <
3310     It,
3311     void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3312     typename It::reference, typename It::iterator_category >>
3313 {
3314     using difference_type = typename It::difference_type;
3315     using value_type = typename It::value_type;
3316     using pointer = typename It::pointer;
3317     using reference = typename It::reference;
3318     using iterator_category = typename It::iterator_category;
3319 };
3320 
3321 // This is required as some compilers implement std::iterator_traits in a way that
3322 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3323 template<typename T, typename = void>
3324 struct iterator_traits
3325 {
3326 };
3327 
3328 template<typename T>
3329 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3330             : iterator_types<T>
3331 {
3332 };
3333 
3334 template<typename T>
3335 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3336 {
3337     using iterator_category = std::random_access_iterator_tag;
3338     using value_type = T;
3339     using difference_type = ptrdiff_t;
3340     using pointer = T*;
3341     using reference = T&;
3342 };
3343 
3344 }  // namespace detail
3345 NLOHMANN_JSON_NAMESPACE_END
3346 
3347 // #include <nlohmann/detail/macro_scope.hpp>
3348 
3349 // #include <nlohmann/detail/meta/call_std/begin.hpp>
3350 //     __ _____ _____ _____
3351 //  __|  |   __|     |   | |  JSON for Modern C++
3352 // |  |  |__   |  |  | | | |  version 3.11.3
3353 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3354 //
3355 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3356 // SPDX-License-Identifier: MIT
3357 
3358 
3359 
3360 // #include <nlohmann/detail/macro_scope.hpp>
3361 
3362 
3363 NLOHMANN_JSON_NAMESPACE_BEGIN
3364 
3365 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3366 
3367 NLOHMANN_JSON_NAMESPACE_END
3368 
3369 // #include <nlohmann/detail/meta/call_std/end.hpp>
3370 //     __ _____ _____ _____
3371 //  __|  |   __|     |   | |  JSON for Modern C++
3372 // |  |  |__   |  |  | | | |  version 3.11.3
3373 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3374 //
3375 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3376 // SPDX-License-Identifier: MIT
3377 
3378 
3379 
3380 // #include <nlohmann/detail/macro_scope.hpp>
3381 
3382 
3383 NLOHMANN_JSON_NAMESPACE_BEGIN
3384 
3385 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3386 
3387 NLOHMANN_JSON_NAMESPACE_END
3388 
3389 // #include <nlohmann/detail/meta/cpp_future.hpp>
3390 
3391 // #include <nlohmann/detail/meta/detected.hpp>
3392 
3393 // #include <nlohmann/json_fwd.hpp>
3394 //     __ _____ _____ _____
3395 //  __|  |   __|     |   | |  JSON for Modern C++
3396 // |  |  |__   |  |  | | | |  version 3.11.3
3397 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
3398 //
3399 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
3400 // SPDX-License-Identifier: MIT
3401 
3402 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3403     #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3404 
3405     #include <cstdint> // int64_t, uint64_t
3406     #include <map> // map
3407     #include <memory> // allocator
3408     #include <string> // string
3409     #include <vector> // vector
3410 
3411     // #include <nlohmann/detail/abi_macros.hpp>
3412 
3413 
3414     /*! 
3415     @brief namespace for Niels Lohmann 
3416     @see https://github.com/nlohmann 
3417     @since version 1.0.0 
3418     */
3419     NLOHMANN_JSON_NAMESPACE_BEGIN
3420 
3421     /*! 
3422     @brief default JSONSerializer template argument 
3423  
3424     This serializer ignores the template arguments and uses ADL 
3425     ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) 
3426     for serialization. 
3427     */
3428     template<typename T = void, typename SFINAE = void>
3429     struct adl_serializer;
3430 
3431     /// a class to store JSON values
3432     /// @sa https://json.nlohmann.me/api/basic_json/
3433     template<template<typename U, typename V, typename... Args> class ObjectType =
3434     std::map,
3435     template<typename U, typename... Args> class ArrayType = std::vector,
3436     class StringType = std::string, class BooleanType = bool,
3437     class NumberIntegerType = std::int64_t,
3438     class NumberUnsignedType = std::uint64_t,
3439     class NumberFloatType = double,
3440     template<typename U> class AllocatorType = std::allocator,
3441     template<typename T, typename SFINAE = void> class JSONSerializer =
3442     adl_serializer,
3443     class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3444     class CustomBaseClass = void>
3445     class basic_json;
3446 
3447     /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
3448     /// @sa https://json.nlohmann.me/api/json_pointer/
3449     template<typename RefStringType>
3450     class json_pointer;
3451 
3452     /*! 
3453     @brief default specialization 
3454     @sa https://json.nlohmann.me/api/json/ 
3455     */
3456     using json = basic_json<>;
3457 
3458     /// @brief a minimal map-like container that preserves insertion order
3459     /// @sa https://json.nlohmann.me/api/ordered_map/
3460     template<class Key, class T, class IgnoredLess, class Allocator>
3461     struct ordered_map;
3462 
3463     /// @brief specialization that maintains the insertion order of object keys
3464     /// @sa https://json.nlohmann.me/api/ordered_json/
3465     using ordered_json = basic_json<nlohmann::ordered_map>;
3466 
3467     NLOHMANN_JSON_NAMESPACE_END
3468 
3469 #endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3470 
3471 
3472 NLOHMANN_JSON_NAMESPACE_BEGIN
3473 /*! 
3474 @brief detail namespace with internal helper functions 
3475  
3476 This namespace collects functions that should not be exposed, 
3477 implementations of some @ref basic_json methods, and meta-programming helpers. 
3478  
3479 @since version 2.1.0 
3480 */
3481 namespace detail
3482 {
3483 
3484 /////////////
3485 // helpers //
3486 /////////////
3487 
3488 // Note to maintainers:
3489 //
3490 // Every trait in this file expects a non CV-qualified type.
3491 // The only exceptions are in the 'aliases for detected' section
3492 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3493 //
3494 // In this case, T has to be properly CV-qualified to constraint the function arguments
3495 // (e.g. to_json(BasicJsonType&, const T&))
3496 
3497 template<typename> struct is_basic_json : std::false_type {};
3498 
3499 NLOHMANN_BASIC_JSON_TPL_DECLARATION
3500 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3501 
3502 // used by exceptions create() member functions
3503 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3504 // false_type otherwise
3505 template<typename BasicJsonContext>
3506 struct is_basic_json_context :
3507     std::integral_constant < bool,
3508     is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3509     || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3510 {};
3511 
3512 //////////////////////
3513 // json_ref helpers //
3514 //////////////////////
3515 
3516 template<typename>
3517 class json_ref;
3518 
3519 template<typename>
3520 struct is_json_ref : std::false_type {};
3521 
3522 template<typename T>
3523 struct is_json_ref<json_ref<T>> : std::true_type {};
3524 
3525 //////////////////////////
3526 // aliases for detected //
3527 //////////////////////////
3528 
3529 template<typename T>
3530 using mapped_type_t = typename T::mapped_type;
3531 
3532 template<typename T>
3533 using key_type_t = typename T::key_type;
3534 
3535 template<typename T>
3536 using value_type_t = typename T::value_type;
3537 
3538 template<typename T>
3539 using difference_type_t = typename T::difference_type;
3540 
3541 template<typename T>
3542 using pointer_t = typename T::pointer;
3543 
3544 template<typename T>
3545 using reference_t = typename T::reference;
3546 
3547 template<typename T>
3548 using iterator_category_t = typename T::iterator_category;
3549 
3550 template<typename T, typename... Args>
3551 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3552 
3553 template<typename T, typename... Args>
3554 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3555 
3556 template<typename T, typename U>
3557 using get_template_function = decltype(std::declval<T>().template get<U>());
3558 
3559 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3560 template<typename BasicJsonType, typename T, typename = void>
3561 struct has_from_json : std::false_type {};
3562 
3563 // trait checking if j.get<T> is valid
3564 // use this trait instead of std::is_constructible or std::is_convertible,
3565 // both rely on, or make use of implicit conversions, and thus fail when T
3566 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3567 template <typename BasicJsonType, typename T>
3568 struct is_getable
3569 {
3570     static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3571 };
3572 
3573 template<typename BasicJsonType, typename T>
3574 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3575 {
3576     using serializer = typename BasicJsonType::template json_serializer<T, void>;
3577 
3578     static constexpr bool value =
3579         is_detected_exact<void, from_json_function, serializer,
3580         const BasicJsonType&, T&>::value;
3581 };
3582 
3583 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3584 // this overload is used for non-default-constructible user-defined-types
3585 template<typename BasicJsonType, typename T, typename = void>
3586 struct has_non_default_from_json : std::false_type {};
3587 
3588 template<typename BasicJsonType, typename T>
3589 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3590 {
3591     using serializer = typename BasicJsonType::template json_serializer<T, void>;
3592 
3593     static constexpr bool value =
3594         is_detected_exact<T, from_json_function, serializer,
3595         const BasicJsonType&>::value;
3596 };
3597 
3598 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3599 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3600 template<typename BasicJsonType, typename T, typename = void>
3601 struct has_to_json : std::false_type {};
3602 
3603 template<typename BasicJsonType, typename T>
3604 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3605 {
3606     using serializer = typename BasicJsonType::template json_serializer<T, void>;
3607 
3608     static constexpr bool value =
3609         is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3610         T>::value;
3611 };
3612 
3613 template<typename T>
3614 using detect_key_compare = typename T::key_compare;
3615 
3616 template<typename T>
3617 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3618 
3619 // obtains the actual object key comparator
3620 template<typename BasicJsonType>
3621 struct actual_object_comparator
3622 {
3623     using object_t = typename BasicJsonType::object_t;
3624     using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3625     using type = typename std::conditional < has_key_compare<object_t>::value,
3626           typename object_t::key_compare, object_comparator_t>::type;
3627 };
3628 
3629 template<typename BasicJsonType>
3630 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3631 
3632 /////////////////
3633 // char_traits //
3634 /////////////////
3635 
3636 // Primary template of char_traits calls std char_traits
3637 template<typename T>
3638 struct char_traits : std::char_traits<T>
3639 {};
3640 
3641 // Explicitly define char traits for unsigned char since it is not standard
3642 template<>
3643 struct char_traits<unsigned char> : std::char_traits<char>
3644 {
3645     using char_type = unsigned char;
3646     using int_type = uint64_t;
3647 
3648     // Redefine to_int_type function
3649     static int_type to_int_type(char_type c) noexcept
3650     {
3651         return static_cast<int_type>(c);
3652     }
3653 
3654     static char_type to_char_type(int_type i) noexcept
3655     {
3656         return static_cast<char_type>(i);
3657     }
3658 
3659     static constexpr int_type eof() noexcept
3660     {
3661         return static_cast<int_type>(EOF);
3662     }
3663 };
3664 
3665 // Explicitly define char traits for signed char since it is not standard
3666 template<>
3667 struct char_traits<signed char> : std::char_traits<char>
3668 {
3669     using char_type = signed char;
3670     using int_type = uint64_t;
3671 
3672     // Redefine to_int_type function
3673     static int_type to_int_type(char_type c) noexcept
3674     {
3675         return static_cast<int_type>(c);
3676     }
3677 
3678     static char_type to_char_type(int_type i) noexcept
3679     {
3680         return static_cast<char_type>(i);
3681     }
3682 
3683     static constexpr int_type eof() noexcept
3684     {
3685         return static_cast<int_type>(EOF);
3686     }
3687 };
3688 
3689 ///////////////////
3690 // is_ functions //
3691 ///////////////////
3692 
3693 // https://en.cppreference.com/w/cpp/types/conjunction
3694 template<class...> struct conjunction : std::true_type { };
3695 template<class B> struct conjunction<B> : B { };
3696 template<class B, class... Bn>
3697 struct conjunction<B, Bn...>
3698 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3699 
3700 // https://en.cppreference.com/w/cpp/types/negation
3701 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3702 
3703 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3704 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3705 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3706 template <typename T>
3707 struct is_default_constructible : std::is_default_constructible<T> {};
3708 
3709 template <typename T1, typename T2>
3710 struct is_default_constructible<std::pair<T1, T2>>
3711             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3712 
3713 template <typename T1, typename T2>
3714 struct is_default_constructible<const std::pair<T1, T2>>
3715             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3716 
3717 template <typename... Ts>
3718 struct is_default_constructible<std::tuple<Ts...>>
3719             : conjunction<is_default_constructible<Ts>...> {};
3720 
3721 template <typename... Ts>
3722 struct is_default_constructible<const std::tuple<Ts...>>
3723             : conjunction<is_default_constructible<Ts>...> {};
3724 
3725 template <typename T, typename... Args>
3726 struct is_constructible : std::is_constructible<T, Args...> {};
3727 
3728 template <typename T1, typename T2>
3729 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3730 
3731 template <typename T1, typename T2>
3732 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3733 
3734 template <typename... Ts>
3735 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3736 
3737 template <typename... Ts>
3738 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3739 
3740 template<typename T, typename = void>
3741 struct is_iterator_traits : std::false_type {};
3742 
3743 template<typename T>
3744 struct is_iterator_traits<iterator_traits<T>>
3745 {
3746   private:
3747     using traits = iterator_traits<T>;
3748 
3749   public:
3750     static constexpr auto value =
3751         is_detected<value_type_t, traits>::value &&
3752         is_detected<difference_type_t, traits>::value &&
3753         is_detected<pointer_t, traits>::value &&
3754         is_detected<iterator_category_t, traits>::value &&
3755         is_detected<reference_t, traits>::value;
3756 };
3757 
3758 template<typename T>
3759 struct is_range
3760 {
3761   private:
3762     using t_ref = typename std::add_lvalue_reference<T>::type;
3763 
3764     using iterator = detected_t<result_of_begin, t_ref>;
3765     using sentinel = detected_t<result_of_end, t_ref>;
3766 
3767     // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3768     // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3769     // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3770     static constexpr auto is_iterator_begin =
3771         is_iterator_traits<iterator_traits<iterator>>::value;
3772 
3773   public:
3774     static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3775 };
3776 
3777 template<typename R>
3778 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3779 
3780 template<typename T>
3781 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3782 
3783 // The following implementation of is_complete_type is taken from
3784 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3785 // and is written by Xiang Fan who agreed to using it in this library.
3786 
3787 template<typename T, typename = void>
3788 struct is_complete_type : std::false_type {};
3789 
3790 template<typename T>
3791 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3792 
3793 template<typename BasicJsonType, typename CompatibleObjectType,
3794          typename = void>
3795 struct is_compatible_object_type_impl : std::false_type {};
3796 
3797 template<typename BasicJsonType, typename CompatibleObjectType>
3798 struct is_compatible_object_type_impl <
3799     BasicJsonType, CompatibleObjectType,
3800     enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3801     is_detected<key_type_t, CompatibleObjectType>::value >>
3802 {
3803     using object_t = typename BasicJsonType::object_t;
3804 
3805     // macOS's is_constructible does not play well with nonesuch...
3806     static constexpr bool value =
3807         is_constructible<typename object_t::key_type,
3808         typename CompatibleObjectType::key_type>::value &&
3809         is_constructible<typename object_t::mapped_type,
3810         typename CompatibleObjectType::mapped_type>::value;
3811 };
3812 
3813 template<typename BasicJsonType, typename CompatibleObjectType>
3814 struct is_compatible_object_type
3815     : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3816 
3817 template<typename BasicJsonType, typename ConstructibleObjectType,
3818          typename = void>
3819 struct is_constructible_object_type_impl : std::false_type {};
3820 
3821 template<typename BasicJsonType, typename ConstructibleObjectType>
3822 struct is_constructible_object_type_impl <
3823     BasicJsonType, ConstructibleObjectType,
3824     enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3825     is_detected<key_type_t, ConstructibleObjectType>::value >>
3826 {
3827     using object_t = typename BasicJsonType::object_t;
3828 
3829     static constexpr bool value =
3830         (is_default_constructible<ConstructibleObjectType>::value &&
3831          (std::is_move_assignable<ConstructibleObjectType>::value ||
3832           std::is_copy_assignable<ConstructibleObjectType>::value) &&
3833          (is_constructible<typename ConstructibleObjectType::key_type,
3834           typename object_t::key_type>::value &&
3835           std::is_same <
3836           typename object_t::mapped_type,
3837           typename ConstructibleObjectType::mapped_type >::value)) ||
3838         (has_from_json<BasicJsonType,
3839          typename ConstructibleObjectType::mapped_type>::value ||
3840          has_non_default_from_json <
3841          BasicJsonType,
3842          typename ConstructibleObjectType::mapped_type >::value);
3843 };
3844 
3845 template<typename BasicJsonType, typename ConstructibleObjectType>
3846 struct is_constructible_object_type
3847     : is_constructible_object_type_impl<BasicJsonType,
3848       ConstructibleObjectType> {};
3849 
3850 template<typename BasicJsonType, typename CompatibleStringType>
3851 struct is_compatible_string_type
3852 {
3853     static constexpr auto value =
3854         is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
3855 };
3856 
3857 template<typename BasicJsonType, typename ConstructibleStringType>
3858 struct is_constructible_string_type
3859 {
3860     // launder type through decltype() to fix compilation failure on ICPC
3861 #ifdef __INTEL_COMPILER
3862     using laundered_type = decltype(std::declval<ConstructibleStringType>());
3863 #else
3864     using laundered_type = ConstructibleStringType;
3865 #endif
3866 
3867     static constexpr auto value =
3868         conjunction <
3869         is_constructible<laundered_type, typename BasicJsonType::string_t>,
3870         is_detected_exact<typename BasicJsonType::string_t::value_type,
3871         value_type_t, laundered_type >>::value;
3872 };
3873 
3874 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3875 struct is_compatible_array_type_impl : std::false_type {};
3876 
3877 template<typename BasicJsonType, typename CompatibleArrayType>
3878 struct is_compatible_array_type_impl <
3879     BasicJsonType, CompatibleArrayType,
3880     enable_if_t <
3881     is_detected<iterator_t, CompatibleArrayType>::value&&
3882     is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3883 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3884 // c.f. https://github.com/nlohmann/json/pull/3073
3885     !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3886 {
3887     static constexpr bool value =
3888         is_constructible<BasicJsonType,
3889         range_value_t<CompatibleArrayType>>::value;
3890 };
3891 
3892 template<typename BasicJsonType, typename CompatibleArrayType>
3893 struct is_compatible_array_type
3894     : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3895 
3896 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3897 struct is_constructible_array_type_impl : std::false_type {};
3898 
3899 template<typename BasicJsonType, typename ConstructibleArrayType>
3900 struct is_constructible_array_type_impl <
3901     BasicJsonType, ConstructibleArrayType,
3902     enable_if_t<std::is_same<ConstructibleArrayType,
3903     typename BasicJsonType::value_type>::value >>
3904             : std::true_type {};
3905 
3906 template<typename BasicJsonType, typename ConstructibleArrayType>
3907 struct is_constructible_array_type_impl <
3908     BasicJsonType, ConstructibleArrayType,
3909     enable_if_t < !std::is_same<ConstructibleArrayType,
3910     typename BasicJsonType::value_type>::value&&
3911     !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3912     is_default_constructible<ConstructibleArrayType>::value&&
3913 (std::is_move_assignable<ConstructibleArrayType>::value ||
3914  std::is_copy_assignable<ConstructibleArrayType>::value)&&
3915 is_detected<iterator_t, ConstructibleArrayType>::value&&
3916 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3917 is_detected<range_value_t, ConstructibleArrayType>::value&&
3918 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3919 // c.f. https://github.com/nlohmann/json/pull/3073
3920 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3921         is_complete_type <
3922         detected_t<range_value_t, ConstructibleArrayType >>::value >>
3923 {
3924     using value_type = range_value_t<ConstructibleArrayType>;
3925 
3926     static constexpr bool value =
3927         std::is_same<value_type,
3928         typename BasicJsonType::array_t::value_type>::value ||
3929         has_from_json<BasicJsonType,
3930         value_type>::value ||
3931         has_non_default_from_json <
3932         BasicJsonType,
3933         value_type >::value;
3934 };
3935 
3936 template<typename BasicJsonType, typename ConstructibleArrayType>
3937 struct is_constructible_array_type
3938     : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3939 
3940 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3941          typename = void>
3942 struct is_compatible_integer_type_impl : std::false_type {};
3943 
3944 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3945 struct is_compatible_integer_type_impl <
3946     RealIntegerType, CompatibleNumberIntegerType,
3947     enable_if_t < std::is_integral<RealIntegerType>::value&&
3948     std::is_integral<CompatibleNumberIntegerType>::value&&
3949     !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3950 {
3951     // is there an assert somewhere on overflows?
3952     using RealLimits = std::numeric_limits<RealIntegerType>;
3953     using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3954 
3955     static constexpr auto value =
3956         is_constructible<RealIntegerType,
3957         CompatibleNumberIntegerType>::value &&
3958         CompatibleLimits::is_integer &&
3959         RealLimits::is_signed == CompatibleLimits::is_signed;
3960 };
3961 
3962 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3963 struct is_compatible_integer_type
3964     : is_compatible_integer_type_impl<RealIntegerType,
3965       CompatibleNumberIntegerType> {};
3966 
3967 template<typename BasicJsonType, typename CompatibleType, typename = void>
3968 struct is_compatible_type_impl: std::false_type {};
3969 
3970 template<typename BasicJsonType, typename CompatibleType>
3971 struct is_compatible_type_impl <
3972     BasicJsonType, CompatibleType,
3973     enable_if_t<is_complete_type<CompatibleType>::value >>
3974 {
3975     static constexpr bool value =
3976         has_to_json<BasicJsonType, CompatibleType>::value;
3977 };
3978 
3979 template<typename BasicJsonType, typename CompatibleType>
3980 struct is_compatible_type
3981     : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3982 
3983 template<typename T1, typename T2>
3984 struct is_constructible_tuple : std::false_type {};
3985 
3986 template<typename T1, typename... Args>
3987 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3988 
3989 template<typename BasicJsonType, typename T>
3990 struct is_json_iterator_of : std::false_type {};
3991 
3992 template<typename BasicJsonType>
3993 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3994 
3995 template<typename BasicJsonType>
3996 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3997 {};
3998 
3999 // checks if a given type T is a template specialization of Primary
4000 template<template <typename...> class Primary, typename T>
4001 struct is_specialization_of : std::false_type {};
4002 
4003 template<template <typename...> class Primary, typename... Args>
4004 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4005 
4006 template<typename T>
4007 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
4008 
4009 // checks if A and B are comparable using Compare functor
4010 template<typename Compare, typename A, typename B, typename = void>
4011 struct is_comparable : std::false_type {};
4012 
4013 template<typename Compare, typename A, typename B>
4014 struct is_comparable<Compare, A, B, void_t<
4015 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4016 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4017 >> : std::true_type {};
4018 
4019 template<typename T>
4020 using detect_is_transparent = typename T::is_transparent;
4021 
4022 // type trait to check if KeyType can be used as object key (without a BasicJsonType)
4023 // see is_usable_as_basic_json_key_type below
4024 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4025          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4026 using is_usable_as_key_type = typename std::conditional <
4027                               is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
4028                               && !(ExcludeObjectKeyType && std::is_same<KeyType,
4029                                    ObjectKeyType>::value)
4030                               && (!RequireTransparentComparator
4031                                   || is_detected <detect_is_transparent, Comparator>::value)
4032                               && !is_json_pointer<KeyType>::value,
4033                               std::true_type,
4034                               std::false_type >::type;
4035 
4036 // type trait to check if KeyType can be used as object key
4037 // true if:
4038 //   - KeyType is comparable with BasicJsonType::object_t::key_type
4039 //   - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4040 //   - the comparator is transparent or RequireTransparentComparator is false
4041 //   - KeyType is not a JSON iterator or json_pointer
4042 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4043          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4044 using is_usable_as_basic_json_key_type = typename std::conditional <
4045         is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4046         typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4047         RequireTransparentComparator, ExcludeObjectKeyType>::value
4048         && !is_json_iterator_of<BasicJsonType, KeyType>::value,
4049         std::true_type,
4050         std::false_type >::type;
4051 
4052 template<typename ObjectType, typename KeyType>
4053 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4054 
4055 // type trait to check if object_t has an erase() member functions accepting KeyType
4056 template<typename BasicJsonType, typename KeyType>
4057 using has_erase_with_key_type = typename std::conditional <
4058                                 is_detected <
4059                                 detect_erase_with_key_type,
4060                                 typename BasicJsonType::object_t, KeyType >::value,
4061                                 std::true_type,
4062                                 std::false_type >::type;
4063 
4064 // a naive helper to check if a type is an ordered_map (exploits the fact that
4065 // ordered_map inherits capacity() from std::vector)
4066 template <typename T>
4067 struct is_ordered_map
4068 {
4069     using one = char;
4070 
4071     struct two
4072     {
4073         char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4074     };
4075 
4076     template <typename C> static one test( decltype(&C::capacity) ) ;
4077     template <typename C> static two test(...);
4078 
4079     enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4080 };
4081 
4082 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4083 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4084 T conditional_static_cast(U value)
4085 {
4086     return static_cast<T>(value);
4087 }
4088 
4089 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4090 T conditional_static_cast(U value)
4091 {
4092     return value;
4093 }
4094 
4095 template<typename... Types>
4096 using all_integral = conjunction<std::is_integral<Types>...>;
4097 
4098 template<typename... Types>
4099 using all_signed = conjunction<std::is_signed<Types>...>;
4100 
4101 template<typename... Types>
4102 using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4103 
4104 // there's a disjunction trait in another PR; replace when merged
4105 template<typename... Types>
4106 using same_sign = std::integral_constant < bool,
4107       all_signed<Types...>::value || all_unsigned<Types...>::value >;
4108 
4109 template<typename OfType, typename T>
4110 using never_out_of_range = std::integral_constant < bool,
4111       (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4112       || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4113 
4114 template<typename OfType, typename T,
4115          bool OfTypeSigned = std::is_signed<OfType>::value,
4116          bool TSigned = std::is_signed<T>::value>
4117 struct value_in_range_of_impl2;
4118 
4119 template<typename OfType, typename T>
4120 struct value_in_range_of_impl2<OfType, T, false, false>
4121 {
4122     static constexpr bool test(T val)
4123     {
4124         using CommonType = typename std::common_type<OfType, T>::type;
4125         return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4126     }
4127 };
4128 
4129 template<typename OfType, typename T>
4130 struct value_in_range_of_impl2<OfType, T, true, false>
4131 {
4132     static constexpr bool test(T val)
4133     {
4134         using CommonType = typename std::common_type<OfType, T>::type;
4135         return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4136     }
4137 };
4138 
4139 template<typename OfType, typename T>
4140 struct value_in_range_of_impl2<OfType, T, false, true>
4141 {
4142     static constexpr bool test(T val)
4143     {
4144         using CommonType = typename std::common_type<OfType, T>::type;
4145         return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4146     }
4147 };
4148 
4149 template<typename OfType, typename T>
4150 struct value_in_range_of_impl2<OfType, T, true, true>
4151 {
4152     static constexpr bool test(T val)
4153     {
4154         using CommonType = typename std::common_type<OfType, T>::type;
4155         return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4156                && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4157     }
4158 };
4159 
4160 template<typename OfType, typename T,
4161          bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4162          typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4163 struct value_in_range_of_impl1;
4164 
4165 template<typename OfType, typename T>
4166 struct value_in_range_of_impl1<OfType, T, false>
4167 {
4168     static constexpr bool test(T val)
4169     {
4170         return value_in_range_of_impl2<OfType, T>::test(val);
4171     }
4172 };
4173 
4174 template<typename OfType, typename T>
4175 struct value_in_range_of_impl1<OfType, T, true>
4176 {
4177     static constexpr bool test(T /*val*/)
4178     {
4179         return true;
4180     }
4181 };
4182 
4183 template<typename OfType, typename T>
4184 constexpr bool value_in_range_of(T val)
4185 {
4186     return value_in_range_of_impl1<OfType, T>::test(val);
4187 }
4188 
4189 template<bool Value>
4190 using bool_constant = std::integral_constant<bool, Value>;
4191 
4192 ///////////////////////////////////////////////////////////////////////////////
4193 // is_c_string
4194 ///////////////////////////////////////////////////////////////////////////////
4195 
4196 namespace impl
4197 {
4198 
4199 template<typename T>
4200 constexpr bool is_c_string()
4201 {
4202     using TUnExt = typename std::remove_extent<T>::type;
4203     using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4204     using TUnPtr = typename std::remove_pointer<T>::type;
4205     using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4206     return
4207         (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4208         || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4209 }
4210 
4211 }  // namespace impl
4212 
4213 // checks whether T is a [cv] char */[cv] char[] C string
4214 template<typename T>
4215 struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4216 
4217 template<typename T>
4218 using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
4219 
4220 ///////////////////////////////////////////////////////////////////////////////
4221 // is_transparent
4222 ///////////////////////////////////////////////////////////////////////////////
4223 
4224 namespace impl
4225 {
4226 
4227 template<typename T>
4228 constexpr bool is_transparent()
4229 {
4230     return is_detected<detect_is_transparent, T>::value;
4231 }
4232 
4233 }  // namespace impl
4234 
4235 // checks whether T has a member named is_transparent
4236 template<typename T>
4237 struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4238 
4239 ///////////////////////////////////////////////////////////////////////////////
4240 
4241 }  // namespace detail
4242 NLOHMANN_JSON_NAMESPACE_END
4243 
4244 // #include <nlohmann/detail/string_concat.hpp>
4245 //     __ _____ _____ _____
4246 //  __|  |   __|     |   | |  JSON for Modern C++
4247 // |  |  |__   |  |  | | | |  version 3.11.3
4248 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
4249 //
4250 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
4251 // SPDX-License-Identifier: MIT
4252 
4253 
4254 
4255 #include <cstring> // strlen
4256 #include <string> // string
4257 #include <utility> // forward
4258 
4259 // #include <nlohmann/detail/meta/cpp_future.hpp>
4260 
4261 // #include <nlohmann/detail/meta/detected.hpp>
4262 
4263 
4264 NLOHMANN_JSON_NAMESPACE_BEGIN
4265 namespace detail
4266 {
4267 
4268 inline std::size_t concat_length()
4269 {
4270     return 0;
4271 }
4272 
4273 template<typename... Args>
4274 inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4275 
4276 template<typename StringType, typename... Args>
4277 inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4278 
4279 template<typename... Args>
4280 inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4281 {
4282     return 1 + concat_length(rest...);
4283 }
4284 
4285 template<typename... Args>
4286 inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4287 {
4288     // cppcheck-suppress ignoredReturnValue
4289     return ::strlen(cstr) + concat_length(rest...);
4290 }
4291 
4292 template<typename StringType, typename... Args>
4293 inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4294 {
4295     return str.size() + concat_length(rest...);
4296 }
4297 
4298 template<typename OutStringType>
4299 inline void concat_into(OutStringType& /*out*/)
4300 {}
4301 
4302 template<typename StringType, typename Arg>
4303 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4304 
4305 template<typename StringType, typename Arg>
4306 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4307 
4308 template<typename StringType, typename Arg>
4309 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4310 
4311 template<typename StringType, typename Arg>
4312 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4313 
4314 template<typename StringType, typename Arg>
4315 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4316 
4317 template<typename StringType, typename Arg>
4318 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4319 
4320 template<typename StringType, typename Arg>
4321 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4322 
4323 template<typename StringType, typename Arg>
4324 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4325 
4326 template < typename OutStringType, typename Arg, typename... Args,
4327            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4328                          && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4329 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4330 
4331 template < typename OutStringType, typename Arg, typename... Args,
4332            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4333                          && !detect_string_can_append_op<OutStringType, Arg>::value
4334                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4335 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4336 
4337 template < typename OutStringType, typename Arg, typename... Args,
4338            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4339                          && !detect_string_can_append_op<OutStringType, Arg>::value
4340                          && !detect_string_can_append_iter<OutStringType, Arg>::value
4341                          && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4342 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4343 
4344 template<typename OutStringType, typename Arg, typename... Args,
4345          enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4346 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4347 {
4348     out.append(std::forward<Arg>(arg));
4349     concat_into(out, std::forward<Args>(rest)...);
4350 }
4351 
4352 template < typename OutStringType, typename Arg, typename... Args,
4353            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4354                          && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4355 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4356 {
4357     out += std::forward<Arg>(arg);
4358     concat_into(out, std::forward<Args>(rest)...);
4359 }
4360 
4361 template < typename OutStringType, typename Arg, typename... Args,
4362            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4363                          && !detect_string_can_append_op<OutStringType, Arg>::value
4364                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4365 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4366 {
4367     out.append(arg.begin(), arg.end());
4368     concat_into(out, std::forward<Args>(rest)...);
4369 }
4370 
4371 template < typename OutStringType, typename Arg, typename... Args,
4372            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4373                          && !detect_string_can_append_op<OutStringType, Arg>::value
4374                          && !detect_string_can_append_iter<OutStringType, Arg>::value
4375                          && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4376 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4377 {
4378     out.append(arg.data(), arg.size());
4379     concat_into(out, std::forward<Args>(rest)...);
4380 }
4381 
4382 template<typename OutStringType = std::string, typename... Args>
4383 inline OutStringType concat(Args && ... args)
4384 {
4385     OutStringType str;
4386     str.reserve(concat_length(args...));
4387     concat_into(str, std::forward<Args>(args)...);
4388     return str;
4389 }
4390 
4391 }  // namespace detail
4392 NLOHMANN_JSON_NAMESPACE_END
4393 
4394 
4395 // With -Wweak-vtables, Clang will complain about the exception classes as they
4396 // have no out-of-line virtual method definitions and their vtable will be
4397 // emitted in every translation unit. This issue cannot be fixed with a
4398 // header-only library as there is no implementation file to move these
4399 // functions to. As a result, we suppress this warning here to avoid client
4400 // code to stumble over this. See https://github.com/nlohmann/json/issues/4087
4401 // for a discussion.
4402 #if defined(__clang__)
4403     #pragma clang diagnostic push
4404     #pragma clang diagnostic ignored "-Wweak-vtables"
4405 #endif
4406 
4407 NLOHMANN_JSON_NAMESPACE_BEGIN
4408 namespace detail
4409 {
4410 
4411 ////////////////
4412 // exceptions //
4413 ////////////////
4414 
4415 /// @brief general exception of the @ref basic_json class
4416 /// @sa https://json.nlohmann.me/api/basic_json/exception/
4417 class exception : public std::exception
4418 {
4419   public:
4420     /// returns the explanatory string
4421     const char* what() const noexcept override
4422     {
4423         return m.what();
4424     }
4425 
4426     /// the id of the exception
4427     const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4428 
4429   protected:
4430     JSON_HEDLEY_NON_NULL(3)
4431     exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4432 
4433     static std::string name(const std::string& ename, int id_)
4434     {
4435         return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4436     }
4437 
4438     static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4439     {
4440         return "";
4441     }
4442 
4443     template<typename BasicJsonType>
4444     static std::string diagnostics(const BasicJsonType* leaf_element)
4445     {
4446 #if JSON_DIAGNOSTICS
4447         std::vector<std::string> tokens;
4448         for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4449         {
4450             switch (current->m_parent->type())
4451             {
4452                 case value_t::array:
4453                 {
4454                     for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4455                     {
4456                         if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4457                         {
4458                             tokens.emplace_back(std::to_string(i));
4459                             break;
4460                         }
4461                     }
4462                     break;
4463                 }
4464 
4465                 case value_t::object:
4466                 {
4467                     for (const auto& element : *current->m_parent->m_data.m_value.object)
4468                     {
4469                         if (&element.second == current)
4470                         {
4471                             tokens.emplace_back(element.first.c_str());
4472                             break;
4473                         }
4474                     }
4475                     break;
4476                 }
4477 
4478                 case value_t::null: // LCOV_EXCL_LINE
4479                 case value_t::string: // LCOV_EXCL_LINE
4480                 case value_t::boolean: // LCOV_EXCL_LINE
4481                 case value_t::number_integer: // LCOV_EXCL_LINE
4482                 case value_t::number_unsigned: // LCOV_EXCL_LINE
4483                 case value_t::number_float: // LCOV_EXCL_LINE
4484                 case value_t::binary: // LCOV_EXCL_LINE
4485                 case value_t::discarded: // LCOV_EXCL_LINE
4486                 default:   // LCOV_EXCL_LINE
4487                     break; // LCOV_EXCL_LINE
4488             }
4489         }
4490 
4491         if (tokens.empty())
4492         {
4493             return "";
4494         }
4495 
4496         auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4497                                    [](const std::string & a, const std::string & b)
4498         {
4499             return concat(a, '/', detail::escape(b));
4500         });
4501         return concat('(', str, ") ");
4502 #else
4503         static_cast<void>(leaf_element);
4504         return "";
4505 #endif
4506     }
4507 
4508   private:
4509     /// an exception object as storage for error messages
4510     std::runtime_error m;
4511 };
4512 
4513 /// @brief exception indicating a parse error
4514 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
4515 class parse_error : public exception
4516 {
4517   public:
4518     /*! 
4519     @brief create a parse error exception 
4520     @param[in] id_       the id of the exception 
4521     @param[in] pos       the position where the error occurred (or with 
4522                          chars_read_total=0 if the position cannot be 
4523                          determined) 
4524     @param[in] what_arg  the explanatory string 
4525     @return parse_error object 
4526     */
4527     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4528     static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4529     {
4530         const std::string w = concat(exception::name("parse_error", id_), "parse error",
4531                                      position_string(pos), ": ", exception::diagnostics(context), what_arg);
4532         return {id_, pos.chars_read_total, w.c_str()};
4533     }
4534 
4535     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4536     static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4537     {
4538         const std::string w = concat(exception::name("parse_error", id_), "parse error",
4539                                      (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4540                                      ": ", exception::diagnostics(context), what_arg);
4541         return {id_, byte_, w.c_str()};
4542     }
4543 
4544     /*! 
4545     @brief byte index of the parse error 
4546  
4547     The byte index of the last read character in the input file. 
4548  
4549     @note For an input with n bytes, 1 is the index of the first character and 
4550           n+1 is the index of the terminating null byte or the end of file. 
4551           This also holds true when reading a byte vector (CBOR or MessagePack). 
4552     */
4553     const std::size_t byte;
4554 
4555   private:
4556     parse_error(int id_, std::size_t byte_, const char* what_arg)
4557         : exception(id_, what_arg), byte(byte_) {}
4558 
4559     static std::string position_string(const position_t& pos)
4560     {
4561         return concat(" at line ", std::to_string(pos.lines_read + 1),
4562                       ", column ", std::to_string(pos.chars_read_current_line));
4563     }
4564 };
4565 
4566 /// @brief exception indicating errors with iterators
4567 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
4568 class invalid_iterator : public exception
4569 {
4570   public:
4571     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4572     static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4573     {
4574         const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4575         return {id_, w.c_str()};
4576     }
4577 
4578   private:
4579     JSON_HEDLEY_NON_NULL(3)
4580     invalid_iterator(int id_, const char* what_arg)
4581         : exception(id_, what_arg) {}
4582 };
4583 
4584 /// @brief exception indicating executing a member function with a wrong type
4585 /// @sa https://json.nlohmann.me/api/basic_json/type_error/
4586 class type_error : public exception
4587 {
4588   public:
4589     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4590     static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4591     {
4592         const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4593         return {id_, w.c_str()};
4594     }
4595 
4596   private:
4597     JSON_HEDLEY_NON_NULL(3)
4598     type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4599 };
4600 
4601 /// @brief exception indicating access out of the defined range
4602 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
4603 class out_of_range : public exception
4604 {
4605   public:
4606     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4607     static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4608     {
4609         const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4610         return {id_, w.c_str()};
4611     }
4612 
4613   private:
4614     JSON_HEDLEY_NON_NULL(3)
4615     out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4616 };
4617 
4618 /// @brief exception indicating other library errors
4619 /// @sa https://json.nlohmann.me/api/basic_json/other_error/
4620 class other_error : public exception
4621 {
4622   public:
4623     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4624     static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4625     {
4626         const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4627         return {id_, w.c_str()};
4628     }
4629 
4630   private:
4631     JSON_HEDLEY_NON_NULL(3)
4632     other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4633 };
4634 
4635 }  // namespace detail
4636 NLOHMANN_JSON_NAMESPACE_END
4637 
4638 #if defined(__clang__)
4639     #pragma clang diagnostic pop
4640 #endif
4641 
4642 // #include <nlohmann/detail/macro_scope.hpp>
4643 
4644 // #include <nlohmann/detail/meta/cpp_future.hpp>
4645 
4646 // #include <nlohmann/detail/meta/identity_tag.hpp>
4647 //     __ _____ _____ _____
4648 //  __|  |   __|     |   | |  JSON for Modern C++
4649 // |  |  |__   |  |  | | | |  version 3.11.3
4650 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
4651 //
4652 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
4653 // SPDX-License-Identifier: MIT
4654 
4655 
4656 
4657 // #include <nlohmann/detail/abi_macros.hpp>
4658 
4659 
4660 NLOHMANN_JSON_NAMESPACE_BEGIN
4661 namespace detail
4662 {
4663 
4664 // dispatching helper struct
4665 template <class T> struct identity_tag {};
4666 
4667 }  // namespace detail
4668 NLOHMANN_JSON_NAMESPACE_END
4669 
4670 // #include <nlohmann/detail/meta/std_fs.hpp>
4671 //     __ _____ _____ _____
4672 //  __|  |   __|     |   | |  JSON for Modern C++
4673 // |  |  |__   |  |  | | | |  version 3.11.3
4674 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
4675 //
4676 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
4677 // SPDX-License-Identifier: MIT
4678 
4679 
4680 
4681 // #include <nlohmann/detail/macro_scope.hpp>
4682 
4683 
4684 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4685 #include <experimental/filesystem>
4686 NLOHMANN_JSON_NAMESPACE_BEGIN
4687 namespace detail
4688 {
4689 namespace std_fs = std::experimental::filesystem;
4690 }  // namespace detail
4691 NLOHMANN_JSON_NAMESPACE_END
4692 #elif JSON_HAS_FILESYSTEM
4693 #include <filesystem> // NOLINT(build/c++17)
4694 NLOHMANN_JSON_NAMESPACE_BEGIN
4695 namespace detail
4696 {
4697 namespace std_fs = std::filesystem;
4698 }  // namespace detail
4699 NLOHMANN_JSON_NAMESPACE_END
4700 #endif
4701 
4702 // #include <nlohmann/detail/meta/type_traits.hpp>
4703 
4704 // #include <nlohmann/detail/string_concat.hpp>
4705 
4706 // #include <nlohmann/detail/value_t.hpp>
4707 
4708 
4709 NLOHMANN_JSON_NAMESPACE_BEGIN
4710 namespace detail
4711 {
4712 
4713 template<typename BasicJsonType>
4714 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4715 {
4716     if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4717     {
4718         JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4719     }
4720     n = nullptr;
4721 }
4722 
4723 #ifdef JSON_HAS_CPP_17
4724 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
4725 template<typename BasicJsonType, typename T>
4726 void from_json(const BasicJsonType& j, std::optional<T>& opt)
4727 {
4728     if (j.is_null())
4729     {
4730         opt = std::nullopt;
4731     }
4732     else
4733     {
4734         opt.emplace(j.template get<T>());
4735     }
4736 }
4737 
4738 #endif // JSON_USE_IMPLICIT_CONVERSIONS
4739 #endif // JSON_HAS_CPP_17
4740 
4741 // overloads for basic_json template parameters
4742 template < typename BasicJsonType, typename ArithmeticType,
4743            enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4744                          !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4745                          int > = 0 >
4746 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4747 {
4748     switch (static_cast<value_t>(j))
4749     {
4750         case value_t::number_unsigned:
4751         {
4752             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4753             break;
4754         }
4755         case value_t::number_integer:
4756         {
4757             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4758             break;
4759         }
4760         case value_t::number_float:
4761         {
4762             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4763             break;
4764         }
4765 
4766         case value_t::null:
4767         case value_t::object:
4768         case value_t::array:
4769         case value_t::string:
4770         case value_t::boolean:
4771         case value_t::binary:
4772         case value_t::discarded:
4773         default:
4774             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4775     }
4776 }
4777 
4778 template<typename BasicJsonType>
4779 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4780 {
4781     if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4782     {
4783         JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4784     }
4785     b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4786 }
4787 
4788 template<typename BasicJsonType>
4789 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4790 {
4791     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4792     {
4793         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4794     }
4795     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4796 }
4797 
4798 template <
4799     typename BasicJsonType, typename StringType,
4800     enable_if_t <
4801         std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4802         && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4803         && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4804         && !is_json_ref<StringType>::value, int > = 0 >
4805 inline void from_json(const BasicJsonType& j, StringType& s)
4806 {
4807     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4808     {
4809         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4810     }
4811 
4812     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4813 }
4814 
4815 template<typename BasicJsonType>
4816 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4817 {
4818     get_arithmetic_value(j, val);
4819 }
4820 
4821 template<typename BasicJsonType>
4822 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4823 {
4824     get_arithmetic_value(j, val);
4825 }
4826 
4827 template<typename BasicJsonType>
4828 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4829 {
4830     get_arithmetic_value(j, val);
4831 }
4832 
4833 #if !JSON_DISABLE_ENUM_SERIALIZATION
4834 template<typename BasicJsonType, typename EnumType,
4835          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4836 inline void from_json(const BasicJsonType& j, EnumType& e)
4837 {
4838     typename std::underlying_type<EnumType>::type val;
4839     get_arithmetic_value(j, val);
4840     e = static_cast<EnumType>(val);
4841 }
4842 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
4843 
4844 // forward_list doesn't have an insert method
4845 template<typename BasicJsonType, typename T, typename Allocator,
4846          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4847 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4848 {
4849     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4850     {
4851         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4852     }
4853     l.clear();
4854     std::transform(j.rbegin(), j.rend(),
4855                    std::front_inserter(l), [](const BasicJsonType & i)
4856     {
4857         return i.template get<T>();
4858     });
4859 }
4860 
4861 // valarray doesn't have an insert method
4862 template<typename BasicJsonType, typename T,
4863          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4864 inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4865 {
4866     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4867     {
4868         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4869     }
4870     l.resize(j.size());
4871     std::transform(j.begin(), j.end(), std::begin(l),
4872                    [](const BasicJsonType & elem)
4873     {
4874         return elem.template get<T>();
4875     });
4876 }
4877 
4878 template<typename BasicJsonType, typename T, std::size_t N>
4879 auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4880 -> decltype(j.template get<T>(), void())
4881 {
4882     for (std::size_t i = 0; i < N; ++i)
4883     {
4884         arr[i] = j.at(i).template get<T>();
4885     }
4886 }
4887 
4888 template<typename BasicJsonType>
4889 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4890 {
4891     arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4892 }
4893 
4894 template<typename BasicJsonType, typename T, std::size_t N>
4895 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4896                           priority_tag<2> /*unused*/)
4897 -> decltype(j.template get<T>(), void())
4898 {
4899     for (std::size_t i = 0; i < N; ++i)
4900     {
4901         arr[i] = j.at(i).template get<T>();
4902     }
4903 }
4904 
4905 template<typename BasicJsonType, typename ConstructibleArrayType,
4906          enable_if_t<
4907              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4908              int> = 0>
4909 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4910 -> decltype(
4911     arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4912     j.template get<typename ConstructibleArrayType::value_type>(),
4913     void())
4914 {
4915     using std::end;
4916 
4917     ConstructibleArrayType ret;
4918     ret.reserve(j.size());
4919     std::transform(j.begin(), j.end(),
4920                    std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4921     {
4922         // get<BasicJsonType>() returns *this, this won't call a from_json
4923         // method when value_type is BasicJsonType
4924         return i.template get<typename ConstructibleArrayType::value_type>();
4925     });
4926     arr = std::move(ret);
4927 }
4928 
4929 template<typename BasicJsonType, typename ConstructibleArrayType,
4930          enable_if_t<
4931              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4932              int> = 0>
4933 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4934                                  priority_tag<0> /*unused*/)
4935 {
4936     using std::end;
4937 
4938     ConstructibleArrayType ret;
4939     std::transform(
4940         j.begin(), j.end(), std::inserter(ret, end(ret)),
4941         [](const BasicJsonType & i)
4942     {
4943         // get<BasicJsonType>() returns *this, this won't call a from_json
4944         // method when value_type is BasicJsonType
4945         return i.template get<typename ConstructibleArrayType::value_type>();
4946     });
4947     arr = std::move(ret);
4948 }
4949 
4950 template < typename BasicJsonType, typename ConstructibleArrayType,
4951            enable_if_t <
4952                is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4953                !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4954                !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4955                !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4956                !is_basic_json<ConstructibleArrayType>::value,
4957                int > = 0 >
4958 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4959 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4960 j.template get<typename ConstructibleArrayType::value_type>(),
4961 void())
4962 {
4963     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4964     {
4965         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4966     }
4967 
4968     from_json_array_impl(j, arr, priority_tag<3> {});
4969 }
4970 
4971 template < typename BasicJsonType, typename T, std::size_t... Idx >
4972 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4973         identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4974 {
4975     return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4976 }
4977 
4978 template < typename BasicJsonType, typename T, std::size_t N >
4979 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4980 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4981 {
4982     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4983     {
4984         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4985     }
4986 
4987     return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4988 }
4989 
4990 template<typename BasicJsonType>
4991 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4992 {
4993     if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4994     {
4995         JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4996     }
4997 
4998     bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4999 }
5000 
5001 template<typename BasicJsonType, typename ConstructibleObjectType,
5002          enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5003 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5004 {
5005     if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5006     {
5007         JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5008     }
5009 
5010     ConstructibleObjectType ret;
5011     const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5012     using value_type = typename ConstructibleObjectType::value_type;
5013     std::transform(
5014         inner_object->begin(), inner_object->end(),
5015         std::inserter(ret, ret.begin()),
5016         [](typename BasicJsonType::object_t::value_type const & p)
5017     {
5018         return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5019     });
5020     obj = std::move(ret);
5021 }
5022 
5023 // overload for arithmetic types, not chosen for basic_json template arguments
5024 // (BooleanType, etc..); note: Is it really necessary to provide explicit
5025 // overloads for boolean_t etc. in case of a custom BooleanType which is not
5026 // an arithmetic type?
5027 template < typename BasicJsonType, typename ArithmeticType,
5028            enable_if_t <
5029                std::is_arithmetic<ArithmeticType>::value&&
5030                !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5031                !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5032                !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5033                !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5034                int > = 0 >
5035 inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5036 {
5037     switch (static_cast<value_t>(j))
5038     {
5039         case value_t::number_unsigned:
5040         {
5041             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5042             break;
5043         }
5044         case value_t::number_integer:
5045         {
5046             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5047             break;
5048         }
5049         case value_t::number_float:
5050         {
5051             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5052             break;
5053         }
5054         case value_t::boolean:
5055         {
5056             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5057             break;
5058         }
5059 
5060         case value_t::null:
5061         case value_t::object:
5062         case value_t::array:
5063         case value_t::string:
5064         case value_t::binary:
5065         case value_t::discarded:
5066         default:
5067             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5068     }
5069 }
5070 
5071 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5072 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5073 {
5074     return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5075 }
5076 
5077 template < typename BasicJsonType, class A1, class A2 >
5078 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5079 {
5080     return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5081             std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5082 }
5083 
5084 template<typename BasicJsonType, typename A1, typename A2>
5085 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5086 {
5087     p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5088 }
5089 
5090 template<typename BasicJsonType, typename... Args>
5091 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5092 {
5093     return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5094 }
5095 
5096 template<typename BasicJsonType, typename... Args>
5097 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5098 {
5099     t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5100 }
5101 
5102 template<typename BasicJsonType, typename TupleRelated>
5103 auto from_json(BasicJsonType&& j, TupleRelated&& t)
5104 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5105 {
5106     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5107     {
5108         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5109     }
5110 
5111     return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5112 }
5113 
5114 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5115            typename = enable_if_t < !std::is_constructible <
5116                                         typename BasicJsonType::string_t, Key >::value >>
5117 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5118 {
5119     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5120     {
5121         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5122     }
5123     m.clear();
5124     for (const auto& p : j)
5125     {
5126         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5127         {
5128             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5129         }
5130         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5131     }
5132 }
5133 
5134 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5135            typename = enable_if_t < !std::is_constructible <
5136                                         typename BasicJsonType::string_t, Key >::value >>
5137 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5138 {
5139     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5140     {
5141         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5142     }
5143     m.clear();
5144     for (const auto& p : j)
5145     {
5146         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5147         {
5148             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5149         }
5150         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5151     }
5152 }
5153 
5154 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5155 template<typename BasicJsonType>
5156 inline void from_json(const BasicJsonType& j, std_fs::path& p)
5157 {
5158     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5159     {
5160         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5161     }
5162     p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5163 }
5164 #endif
5165 
5166 struct from_json_fn
5167 {
5168     template<typename BasicJsonType, typename T>
5169     auto operator()(const BasicJsonType& j, T&& val) const
5170     noexcept(noexcept(from_json(j, std::forward<T>(val))))
5171     -> decltype(from_json(j, std::forward<T>(val)))
5172     {
5173         return from_json(j, std::forward<T>(val));
5174     }
5175 };
5176 
5177 }  // namespace detail
5178 
5179 #ifndef JSON_HAS_CPP_17
5180 /// namespace to hold default `from_json` function
5181 /// to see why this is required:
5182 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5183 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5184 {
5185 #endif
5186 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5187     detail::static_const<detail::from_json_fn>::value;
5188 #ifndef JSON_HAS_CPP_17
5189 }  // namespace
5190 #endif
5191 
5192 NLOHMANN_JSON_NAMESPACE_END
5193 
5194 // #include <nlohmann/detail/conversions/to_json.hpp>
5195 //     __ _____ _____ _____
5196 //  __|  |   __|     |   | |  JSON for Modern C++
5197 // |  |  |__   |  |  | | | |  version 3.11.3
5198 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5199 //
5200 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
5201 // SPDX-License-Identifier: MIT
5202 
5203 
5204 
5205 #include <algorithm> // copy
5206 #include <iterator> // begin, end
5207 #ifdef JSON_HAS_CPP_17
5208     #include <optional> // optional
5209 #endif
5210 #include <string> // string
5211 #include <tuple> // tuple, get
5212 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5213 #include <utility> // move, forward, declval, pair
5214 #include <valarray> // valarray
5215 #include <vector> // vector
5216 
5217 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5218 //     __ _____ _____ _____
5219 //  __|  |   __|     |   | |  JSON for Modern C++
5220 // |  |  |__   |  |  | | | |  version 3.11.3
5221 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5222 //
5223 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
5224 // SPDX-License-Identifier: MIT
5225 
5226 
5227 
5228 #include <cstddef> // size_t
5229 #include <iterator> // forward_iterator_tag
5230 #include <string> // string, to_string
5231 #include <tuple> // tuple_size, get, tuple_element
5232 #include <utility> // move
5233 
5234 #if JSON_HAS_RANGES
5235     #include <ranges> // enable_borrowed_range
5236 #endif
5237 
5238 // #include <nlohmann/detail/abi_macros.hpp>
5239 
5240 // #include <nlohmann/detail/meta/type_traits.hpp>
5241 
5242 // #include <nlohmann/detail/value_t.hpp>
5243 
5244 
5245 NLOHMANN_JSON_NAMESPACE_BEGIN
5246 namespace detail
5247 {
5248 
5249 template<typename string_type>
5250 void int_to_string( string_type& target, std::size_t value )
5251 {
5252     // For ADL
5253     using std::to_string;
5254     target = to_string(value);
5255 }
5256 template<typename IteratorType> class iteration_proxy_value
5257 {
5258   public:
5259     using difference_type = std::ptrdiff_t;
5260     using value_type = iteration_proxy_value;
5261     using pointer = value_type *;
5262     using reference = value_type &;
5263     using iterator_category = std::forward_iterator_tag;
5264     using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5265 
5266   private:
5267     /// the iterator
5268     IteratorType anchor{};
5269     /// an index for arrays (used to create key names)
5270     std::size_t array_index = 0;
5271     /// last stringified array index
5272     mutable std::size_t array_index_last = 0;
5273     /// a string representation of the array index
5274     mutable string_type array_index_str = "0";
5275     /// an empty string (to return a reference for primitive values)
5276     string_type empty_str{};
5277 
5278   public:
5279     explicit iteration_proxy_value() = default;
5280     explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5281     noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5282              && std::is_nothrow_default_constructible<string_type>::value)
5283         : anchor(std::move(it))
5284         , array_index(array_index_)
5285     {}
5286 
5287     iteration_proxy_value(iteration_proxy_value const&) = default;
5288     iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5289     // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5290     iteration_proxy_value(iteration_proxy_value&&)
5291     noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5292              && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5293     iteration_proxy_value& operator=(iteration_proxy_value&&)
5294     noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5295              && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5296     ~iteration_proxy_value() = default;
5297 
5298     /// dereference operator (needed for range-based for)
5299     const iteration_proxy_value& operator*() const
5300     {
5301         return *this;
5302     }
5303 
5304     /// increment operator (needed for range-based for)
5305     iteration_proxy_value& operator++()
5306     {
5307         ++anchor;
5308         ++array_index;
5309 
5310         return *this;
5311     }
5312 
5313     iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5314     {
5315         auto tmp = iteration_proxy_value(anchor, array_index);
5316         ++anchor;
5317         ++array_index;
5318         return tmp;
5319     }
5320 
5321     /// equality operator (needed for InputIterator)
5322     bool operator==(const iteration_proxy_value& o) const
5323     {
5324         return anchor == o.anchor;
5325     }
5326 
5327     /// inequality operator (needed for range-based for)
5328     bool operator!=(const iteration_proxy_value& o) const
5329     {
5330         return anchor != o.anchor;
5331     }
5332 
5333     /// return key of the iterator
5334     const string_type& key() const
5335     {
5336         JSON_ASSERT(anchor.m_object != nullptr);
5337 
5338         switch (anchor.m_object->type())
5339         {
5340             // use integer array index as key
5341             case value_t::array:
5342             {
5343                 if (array_index != array_index_last)
5344                 {
5345                     int_to_string( array_index_str, array_index );
5346                     array_index_last = array_index;
5347                 }
5348                 return array_index_str;
5349             }
5350 
5351             // use key from the object
5352             case value_t::object:
5353                 return anchor.key();
5354 
5355             // use an empty key for all primitive types
5356             case value_t::null:
5357             case value_t::string:
5358             case value_t::boolean:
5359             case value_t::number_integer:
5360             case value_t::number_unsigned:
5361             case value_t::number_float:
5362             case value_t::binary:
5363             case value_t::discarded:
5364             default:
5365                 return empty_str;
5366         }
5367     }
5368 
5369     /// return value of the iterator
5370     typename IteratorType::reference value() const
5371     {
5372         return anchor.value();
5373     }
5374 };
5375 
5376 /// proxy class for the items() function
5377 template<typename IteratorType> class iteration_proxy
5378 {
5379   private:
5380     /// the container to iterate
5381     typename IteratorType::pointer container = nullptr;
5382 
5383   public:
5384     explicit iteration_proxy() = default;
5385 
5386     /// construct iteration proxy from a container
5387     explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5388         : container(&cont) {}
5389 
5390     iteration_proxy(iteration_proxy const&) = default;
5391     iteration_proxy& operator=(iteration_proxy const&) = default;
5392     iteration_proxy(iteration_proxy&&) noexcept = default;
5393     iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5394     ~iteration_proxy() = default;
5395 
5396     /// return iterator begin (needed for range-based for)
5397     iteration_proxy_value<IteratorType> begin() const noexcept
5398     {
5399         return iteration_proxy_value<IteratorType>(container->begin());
5400     }
5401 
5402     /// return iterator end (needed for range-based for)
5403     iteration_proxy_value<IteratorType> end() const noexcept
5404     {
5405         return iteration_proxy_value<IteratorType>(container->end());
5406     }
5407 };
5408 
5409 // Structured Bindings Support
5410 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5411 // And see https://github.com/nlohmann/json/pull/1391
5412 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5413 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5414 {
5415     return i.key();
5416 }
5417 // Structured Bindings Support
5418 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5419 // And see https://github.com/nlohmann/json/pull/1391
5420 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5421 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5422 {
5423     return i.value();
5424 }
5425 
5426 }  // namespace detail
5427 NLOHMANN_JSON_NAMESPACE_END
5428 
5429 // The Addition to the STD Namespace is required to add
5430 // Structured Bindings Support to the iteration_proxy_value class
5431 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5432 // And see https://github.com/nlohmann/json/pull/1391
5433 namespace std
5434 {
5435 
5436 #if defined(__clang__)
5437     // Fix: https://github.com/nlohmann/json/issues/1401
5438     #pragma clang diagnostic push
5439     #pragma clang diagnostic ignored "-Wmismatched-tags"
5440 #endif
5441 template<typename IteratorType>
5442 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5443             : public std::integral_constant<std::size_t, 2> {};
5444 
5445 template<std::size_t N, typename IteratorType>
5446 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5447 {
5448   public:
5449     using type = decltype(
5450                      get<N>(std::declval <
5451                             ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5452 };
5453 #if defined(__clang__)
5454     #pragma clang diagnostic pop
5455 #endif
5456 
5457 }  // namespace std
5458 
5459 #if JSON_HAS_RANGES
5460     template <typename IteratorType>
5461     inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5462 #endif
5463 
5464 // #include <nlohmann/detail/macro_scope.hpp>
5465 
5466 // #include <nlohmann/detail/meta/cpp_future.hpp>
5467 
5468 // #include <nlohmann/detail/meta/std_fs.hpp>
5469 
5470 // #include <nlohmann/detail/meta/type_traits.hpp>
5471 
5472 // #include <nlohmann/detail/value_t.hpp>
5473 
5474 
5475 NLOHMANN_JSON_NAMESPACE_BEGIN
5476 namespace detail
5477 {
5478 
5479 //////////////////
5480 // constructors //
5481 //////////////////
5482 
5483 /* 
5484  * Note all external_constructor<>::construct functions need to call 
5485  * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an 
5486  * allocated value (e.g., a string). See bug issue 
5487  * https://github.com/nlohmann/json/issues/2865 for more information. 
5488  */
5489 
5490 template<value_t> struct external_constructor;
5491 
5492 template<>
5493 struct external_constructor<value_t::boolean>
5494 {
5495     template<typename BasicJsonType>
5496     static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5497     {
5498         j.m_data.m_value.destroy(j.m_data.m_type);
5499         j.m_data.m_type = value_t::boolean;
5500         j.m_data.m_value = b;
5501         j.assert_invariant();
5502     }
5503 };
5504 
5505 template<>
5506 struct external_constructor<value_t::string>
5507 {
5508     template<typename BasicJsonType>
5509     static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5510     {
5511         j.m_data.m_value.destroy(j.m_data.m_type);
5512         j.m_data.m_type = value_t::string;
5513         j.m_data.m_value = s;
5514         j.assert_invariant();
5515     }
5516 
5517     template<typename BasicJsonType>
5518     static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5519     {
5520         j.m_data.m_value.destroy(j.m_data.m_type);
5521         j.m_data.m_type = value_t::string;
5522         j.m_data.m_value = std::move(s);
5523         j.assert_invariant();
5524     }
5525 
5526     template < typename BasicJsonType, typename CompatibleStringType,
5527                enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5528                              int > = 0 >
5529     static void construct(BasicJsonType& j, const CompatibleStringType& str)
5530     {
5531         j.m_data.m_value.destroy(j.m_data.m_type);
5532         j.m_data.m_type = value_t::string;
5533         j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5534         j.assert_invariant();
5535     }
5536 };
5537 
5538 template<>
5539 struct external_constructor<value_t::binary>
5540 {
5541     template<typename BasicJsonType>
5542     static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5543     {
5544         j.m_data.m_value.destroy(j.m_data.m_type);
5545         j.m_data.m_type = value_t::binary;
5546         j.m_data.m_value = typename BasicJsonType::binary_t(b);
5547         j.assert_invariant();
5548     }
5549 
5550     template<typename BasicJsonType>
5551     static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5552     {
5553         j.m_data.m_value.destroy(j.m_data.m_type);
5554         j.m_data.m_type = value_t::binary;
5555         j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5556         j.assert_invariant();
5557     }
5558 };
5559 
5560 template<>
5561 struct external_constructor<value_t::number_float>
5562 {
5563     template<typename BasicJsonType>
5564     static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5565     {
5566         j.m_data.m_value.destroy(j.m_data.m_type);
5567         j.m_data.m_type = value_t::number_float;
5568         j.m_data.m_value = val;
5569         j.assert_invariant();
5570     }
5571 };
5572 
5573 template<>
5574 struct external_constructor<value_t::number_unsigned>
5575 {
5576     template<typename BasicJsonType>
5577     static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5578     {
5579         j.m_data.m_value.destroy(j.m_data.m_type);
5580         j.m_data.m_type = value_t::number_unsigned;
5581         j.m_data.m_value = val;
5582         j.assert_invariant();
5583     }
5584 };
5585 
5586 template<>
5587 struct external_constructor<value_t::number_integer>
5588 {
5589     template<typename BasicJsonType>
5590     static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5591     {
5592         j.m_data.m_value.destroy(j.m_data.m_type);
5593         j.m_data.m_type = value_t::number_integer;
5594         j.m_data.m_value = val;
5595         j.assert_invariant();
5596     }
5597 };
5598 
5599 template<>
5600 struct external_constructor<value_t::array>
5601 {
5602     template<typename BasicJsonType>
5603     static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5604     {
5605         j.m_data.m_value.destroy(j.m_data.m_type);
5606         j.m_data.m_type = value_t::array;
5607         j.m_data.m_value = arr;
5608         j.set_parents();
5609         j.assert_invariant();
5610     }
5611 
5612     template<typename BasicJsonType>
5613     static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5614     {
5615         j.m_data.m_value.destroy(j.m_data.m_type);
5616         j.m_data.m_type = value_t::array;
5617         j.m_data.m_value = std::move(arr);
5618         j.set_parents();
5619         j.assert_invariant();
5620     }
5621 
5622     template < typename BasicJsonType, typename CompatibleArrayType,
5623                enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5624                              int > = 0 >
5625     static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5626     {
5627         using std::begin;
5628         using std::end;
5629 
5630         j.m_data.m_value.destroy(j.m_data.m_type);
5631         j.m_data.m_type = value_t::array;
5632         j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5633         j.set_parents();
5634         j.assert_invariant();
5635     }
5636 
5637     template<typename BasicJsonType>
5638     static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5639     {
5640         j.m_data.m_value.destroy(j.m_data.m_type);
5641         j.m_data.m_type = value_t::array;
5642         j.m_data.m_value = value_t::array;
5643         j.m_data.m_value.array->reserve(arr.size());
5644         for (const bool x : arr)
5645         {
5646             j.m_data.m_value.array->push_back(x);
5647             j.set_parent(j.m_data.m_value.array->back());
5648         }
5649         j.assert_invariant();
5650     }
5651 
5652     template<typename BasicJsonType, typename T,
5653              enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5654     static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5655     {
5656         j.m_data.m_value.destroy(j.m_data.m_type);
5657         j.m_data.m_type = value_t::array;
5658         j.m_data.m_value = value_t::array;
5659         j.m_data.m_value.array->resize(arr.size());
5660         if (arr.size() > 0)
5661         {
5662             std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5663         }
5664         j.set_parents();
5665         j.assert_invariant();
5666     }
5667 };
5668 
5669 template<>
5670 struct external_constructor<value_t::object>
5671 {
5672     template<typename BasicJsonType>
5673     static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5674     {
5675         j.m_data.m_value.destroy(j.m_data.m_type);
5676         j.m_data.m_type = value_t::object;
5677         j.m_data.m_value = obj;
5678         j.set_parents();
5679         j.assert_invariant();
5680     }
5681 
5682     template<typename BasicJsonType>
5683     static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5684     {
5685         j.m_data.m_value.destroy(j.m_data.m_type);
5686         j.m_data.m_type = value_t::object;
5687         j.m_data.m_value = std::move(obj);
5688         j.set_parents();
5689         j.assert_invariant();
5690     }
5691 
5692     template < typename BasicJsonType, typename CompatibleObjectType,
5693                enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5694     static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5695     {
5696         using std::begin;
5697         using std::end;
5698 
5699         j.m_data.m_value.destroy(j.m_data.m_type);
5700         j.m_data.m_type = value_t::object;
5701         j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5702         j.set_parents();
5703         j.assert_invariant();
5704     }
5705 };
5706 
5707 /////////////
5708 // to_json //
5709 /////////////
5710 
5711 #ifdef JSON_HAS_CPP_17
5712 template<typename BasicJsonType, typename T,
5713          enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5714 void to_json(BasicJsonType& j, const std::optional<T>& opt)
5715 {
5716     if (opt.has_value())
5717     {
5718         j = *opt;
5719     }
5720     else
5721     {
5722         j = nullptr;
5723     }
5724 }
5725 #endif
5726 
5727 template<typename BasicJsonType, typename T,
5728          enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5729 inline void to_json(BasicJsonType& j, T b) noexcept
5730 {
5731     external_constructor<value_t::boolean>::construct(j, b);
5732 }
5733 
5734 template < typename BasicJsonType, typename BoolRef,
5735            enable_if_t <
5736                ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5737                  && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5738                 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5739                     && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5740                                       typename BasicJsonType::boolean_t >::value))
5741                && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5742 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5743 {
5744     external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5745 }
5746 
5747 template<typename BasicJsonType, typename CompatibleString,
5748          enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5749 inline void to_json(BasicJsonType& j, const CompatibleString& s)
5750 {
5751     external_constructor<value_t::string>::construct(j, s);
5752 }
5753 
5754 template<typename BasicJsonType>
5755 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5756 {
5757     external_constructor<value_t::string>::construct(j, std::move(s));
5758 }
5759 
5760 template<typename BasicJsonType, typename FloatType,
5761          enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5762 inline void to_json(BasicJsonType& j, FloatType val) noexcept
5763 {
5764     external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5765 }
5766 
5767 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5768          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5769 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5770 {
5771     external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5772 }
5773 
5774 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5775          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5776 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5777 {
5778     external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5779 }
5780 
5781 #if !JSON_DISABLE_ENUM_SERIALIZATION
5782 template<typename BasicJsonType, typename EnumType,
5783          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5784 inline void to_json(BasicJsonType& j, EnumType e) noexcept
5785 {
5786     using underlying_type = typename std::underlying_type<EnumType>::type;
5787     static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
5788     external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
5789 }
5790 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
5791 
5792 template<typename BasicJsonType>
5793 inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5794 {
5795     external_constructor<value_t::array>::construct(j, e);
5796 }
5797 
5798 template < typename BasicJsonType, typename CompatibleArrayType,
5799            enable_if_t < is_compatible_array_type<BasicJsonType,
5800                          CompatibleArrayType>::value&&
5801                          !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5802                          !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5803                          !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5804                          !is_basic_json<CompatibleArrayType>::value,
5805                          int > = 0 >
5806 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5807 {
5808     external_constructor<value_t::array>::construct(j, arr);
5809 }
5810 
5811 template<typename BasicJsonType>
5812 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5813 {
5814     external_constructor<value_t::binary>::construct(j, bin);
5815 }
5816 
5817 template<typename BasicJsonType, typename T,
5818          enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5819 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5820 {
5821     external_constructor<value_t::array>::construct(j, std::move(arr));
5822 }
5823 
5824 template<typename BasicJsonType>
5825 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5826 {
5827     external_constructor<value_t::array>::construct(j, std::move(arr));
5828 }
5829 
5830 template < typename BasicJsonType, typename CompatibleObjectType,
5831            enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5832 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5833 {
5834     external_constructor<value_t::object>::construct(j, obj);
5835 }
5836 
5837 template<typename BasicJsonType>
5838 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5839 {
5840     external_constructor<value_t::object>::construct(j, std::move(obj));
5841 }
5842 
5843 template <
5844     typename BasicJsonType, typename T, std::size_t N,
5845     enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5846                   const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5847                   int > = 0 >
5848 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5849 {
5850     external_constructor<value_t::array>::construct(j, arr);
5851 }
5852 
5853 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5854 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5855 {
5856     j = { p.first, p.second };
5857 }
5858 
5859 // for https://github.com/nlohmann/json/pull/1134
5860 template<typename BasicJsonType, typename T,
5861          enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5862 inline void to_json(BasicJsonType& j, const T& b)
5863 {
5864     j = { {b.key(), b.value()} };
5865 }
5866 
5867 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5868 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5869 {
5870     j = { std::get<Idx>(t)... };
5871 }
5872 
5873 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5874 inline void to_json(BasicJsonType& j, const T& t)
5875 {
5876     to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5877 }
5878 
5879 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5880 template<typename BasicJsonType>
5881 inline void to_json(BasicJsonType& j, const std_fs::path& p)
5882 {
5883     j = p.string();
5884 }
5885 #endif
5886 
5887 struct to_json_fn
5888 {
5889     template<typename BasicJsonType, typename T>
5890     auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5891     -> decltype(to_json(j, std::forward<T>(val)), void())
5892     {
5893         return to_json(j, std::forward<T>(val));
5894     }
5895 };
5896 }  // namespace detail
5897 
5898 #ifndef JSON_HAS_CPP_17
5899 /// namespace to hold default `to_json` function
5900 /// to see why this is required:
5901 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
5902 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5903 {
5904 #endif
5905 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5906     detail::static_const<detail::to_json_fn>::value;
5907 #ifndef JSON_HAS_CPP_17
5908 }  // namespace
5909 #endif
5910 
5911 NLOHMANN_JSON_NAMESPACE_END
5912 
5913 // #include <nlohmann/detail/meta/identity_tag.hpp>
5914 
5915 
5916 NLOHMANN_JSON_NAMESPACE_BEGIN
5917 
5918 /// @sa https://json.nlohmann.me/api/adl_serializer/
5919 template<typename ValueType, typename>
5920 struct adl_serializer
5921 {
5922     /// @brief convert a JSON value to any value type
5923     /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5924     template<typename BasicJsonType, typename TargetType = ValueType>
5925     static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5926         noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5927     -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5928     {
5929         ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5930     }
5931 
5932     /// @brief convert a JSON value to any value type
5933     /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
5934     template<typename BasicJsonType, typename TargetType = ValueType>
5935     static auto from_json(BasicJsonType && j) noexcept(
5936     noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5937     -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5938     {
5939         return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5940     }
5941 
5942     /// @brief convert any value type to a JSON value
5943     /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
5944     template<typename BasicJsonType, typename TargetType = ValueType>
5945     static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5946         noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5947     -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5948     {
5949         ::nlohmann::to_json(j, std::forward<TargetType>(val));
5950     }
5951 };
5952 
5953 NLOHMANN_JSON_NAMESPACE_END
5954 
5955 // #include <nlohmann/byte_container_with_subtype.hpp>
5956 //     __ _____ _____ _____
5957 //  __|  |   __|     |   | |  JSON for Modern C++
5958 // |  |  |__   |  |  | | | |  version 3.11.3
5959 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5960 //
5961 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
5962 // SPDX-License-Identifier: MIT
5963 
5964 
5965 
5966 #include <cstdint> // uint8_t, uint64_t
5967 #include <tuple> // tie
5968 #include <utility> // move
5969 
5970 // #include <nlohmann/detail/abi_macros.hpp>
5971 
5972 
5973 NLOHMANN_JSON_NAMESPACE_BEGIN
5974 
5975 /// @brief an internal type for a backed binary type
5976 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
5977 template<typename BinaryType>
5978 class byte_container_with_subtype : public BinaryType
5979 {
5980   public:
5981     using container_type = BinaryType;
5982     using subtype_type = std::uint64_t;
5983 
5984     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5985     byte_container_with_subtype() noexcept(noexcept(container_type()))
5986         : container_type()
5987     {}
5988 
5989     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5990     byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5991         : container_type(b)
5992     {}
5993 
5994     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
5995     byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5996         : container_type(std::move(b))
5997     {}
5998 
5999     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6000     byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
6001         : container_type(b)
6002         , m_subtype(subtype_)
6003         , m_has_subtype(true)
6004     {}
6005 
6006     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
6007     byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6008         : container_type(std::move(b))
6009         , m_subtype(subtype_)
6010         , m_has_subtype(true)
6011     {}
6012 
6013     bool operator==(const byte_container_with_subtype& rhs) const
6014     {
6015         return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6016                std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6017     }
6018 
6019     bool operator!=(const byte_container_with_subtype& rhs) const
6020     {
6021         return !(rhs == *this);
6022     }
6023 
6024     /// @brief sets the binary subtype
6025     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
6026     void set_subtype(subtype_type subtype_) noexcept
6027     {
6028         m_subtype = subtype_;
6029         m_has_subtype = true;
6030     }
6031 
6032     /// @brief return the binary subtype
6033     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
6034     constexpr subtype_type subtype() const noexcept
6035     {
6036         return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6037     }
6038 
6039     /// @brief return whether the value has a subtype
6040     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
6041     constexpr bool has_subtype() const noexcept
6042     {
6043         return m_has_subtype;
6044     }
6045 
6046     /// @brief clears the binary subtype
6047     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
6048     void clear_subtype() noexcept
6049     {
6050         m_subtype = 0;
6051         m_has_subtype = false;
6052     }
6053 
6054   private:
6055     subtype_type m_subtype = 0;
6056     bool m_has_subtype = false;
6057 };
6058 
6059 NLOHMANN_JSON_NAMESPACE_END
6060 
6061 // #include <nlohmann/detail/conversions/from_json.hpp>
6062 
6063 // #include <nlohmann/detail/conversions/to_json.hpp>
6064 
6065 // #include <nlohmann/detail/exceptions.hpp>
6066 
6067 // #include <nlohmann/detail/hash.hpp>
6068 //     __ _____ _____ _____
6069 //  __|  |   __|     |   | |  JSON for Modern C++
6070 // |  |  |__   |  |  | | | |  version 3.11.3
6071 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6072 //
6073 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6074 // SPDX-License-Identifier: MIT
6075 
6076 
6077 
6078 #include <cstdint> // uint8_t
6079 #include <cstddef> // size_t
6080 #include <functional> // hash
6081 
6082 // #include <nlohmann/detail/abi_macros.hpp>
6083 
6084 // #include <nlohmann/detail/value_t.hpp>
6085 
6086 
6087 NLOHMANN_JSON_NAMESPACE_BEGIN
6088 namespace detail
6089 {
6090 
6091 // boost::hash_combine
6092 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6093 {
6094     seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6095     return seed;
6096 }
6097 
6098 /*! 
6099 @brief hash a JSON value 
6100  
6101 The hash function tries to rely on std::hash where possible. Furthermore, the 
6102 type of the JSON value is taken into account to have different hash values for 
6103 null, 0, 0U, and false, etc. 
6104  
6105 @tparam BasicJsonType basic_json specialization 
6106 @param j JSON value to hash 
6107 @return hash value of j 
6108 */
6109 template<typename BasicJsonType>
6110 std::size_t hash(const BasicJsonType& j)
6111 {
6112     using string_t = typename BasicJsonType::string_t;
6113     using number_integer_t = typename BasicJsonType::number_integer_t;
6114     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6115     using number_float_t = typename BasicJsonType::number_float_t;
6116 
6117     const auto type = static_cast<std::size_t>(j.type());
6118     switch (j.type())
6119     {
6120         case BasicJsonType::value_t::null:
6121         case BasicJsonType::value_t::discarded:
6122         {
6123             return combine(type, 0);
6124         }
6125 
6126         case BasicJsonType::value_t::object:
6127         {
6128             auto seed = combine(type, j.size());
6129             for (const auto& element : j.items())
6130             {
6131                 const auto h = std::hash<string_t> {}(element.key());
6132                 seed = combine(seed, h);
6133                 seed = combine(seed, hash(element.value()));
6134             }
6135             return seed;
6136         }
6137 
6138         case BasicJsonType::value_t::array:
6139         {
6140             auto seed = combine(type, j.size());
6141             for (const auto& element : j)
6142             {
6143                 seed = combine(seed, hash(element));
6144             }
6145             return seed;
6146         }
6147 
6148         case BasicJsonType::value_t::string:
6149         {
6150             const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6151             return combine(type, h);
6152         }
6153 
6154         case BasicJsonType::value_t::boolean:
6155         {
6156             const auto h = std::hash<bool> {}(j.template get<bool>());
6157             return combine(type, h);
6158         }
6159 
6160         case BasicJsonType::value_t::number_integer:
6161         {
6162             const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6163             return combine(type, h);
6164         }
6165 
6166         case BasicJsonType::value_t::number_unsigned:
6167         {
6168             const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6169             return combine(type, h);
6170         }
6171 
6172         case BasicJsonType::value_t::number_float:
6173         {
6174             const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6175             return combine(type, h);
6176         }
6177 
6178         case BasicJsonType::value_t::binary:
6179         {
6180             auto seed = combine(type, j.get_binary().size());
6181             const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6182             seed = combine(seed, h);
6183             seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6184             for (const auto byte : j.get_binary())
6185             {
6186                 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6187             }
6188             return seed;
6189         }
6190 
6191         default:                   // LCOV_EXCL_LINE
6192             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6193             return 0;              // LCOV_EXCL_LINE
6194     }
6195 }
6196 
6197 }  // namespace detail
6198 NLOHMANN_JSON_NAMESPACE_END
6199 
6200 // #include <nlohmann/detail/input/binary_reader.hpp>
6201 //     __ _____ _____ _____
6202 //  __|  |   __|     |   | |  JSON for Modern C++
6203 // |  |  |__   |  |  | | | |  version 3.11.3
6204 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6205 //
6206 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6207 // SPDX-License-Identifier: MIT
6208 
6209 
6210 
6211 #include <algorithm> // generate_n
6212 #include <array> // array
6213 #include <cmath> // ldexp
6214 #include <cstddef> // size_t
6215 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6216 #include <cstdio> // snprintf
6217 #include <cstring> // memcpy
6218 #include <iterator> // back_inserter
6219 #include <limits> // numeric_limits
6220 #include <string> // char_traits, string
6221 #include <utility> // make_pair, move
6222 #include <vector> // vector
6223 #ifdef __cpp_lib_byteswap
6224     #include <bit>  //byteswap
6225 #endif
6226 
6227 // #include <nlohmann/detail/exceptions.hpp>
6228 
6229 // #include <nlohmann/detail/input/input_adapters.hpp>
6230 //     __ _____ _____ _____
6231 //  __|  |   __|     |   | |  JSON for Modern C++
6232 // |  |  |__   |  |  | | | |  version 3.11.3
6233 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6234 //
6235 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6236 // SPDX-License-Identifier: MIT
6237 
6238 
6239 
6240 #include <array> // array
6241 #include <cstddef> // size_t
6242 #include <cstring> // strlen
6243 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6244 #include <memory> // shared_ptr, make_shared, addressof
6245 #include <numeric> // accumulate
6246 #include <string> // string, char_traits
6247 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6248 #include <utility> // pair, declval
6249 
6250 #ifndef JSON_NO_IO
6251     #include <cstdio>   // FILE *
6252     #include <istream>  // istream
6253 #endif                  // JSON_NO_IO
6254 
6255 // #include <nlohmann/detail/exceptions.hpp>
6256 
6257 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
6258 
6259 // #include <nlohmann/detail/macro_scope.hpp>
6260 
6261 // #include <nlohmann/detail/meta/type_traits.hpp>
6262 
6263 
6264 NLOHMANN_JSON_NAMESPACE_BEGIN
6265 namespace detail
6266 {
6267 
6268 /// the supported input formats
6269 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6270 
6271 ////////////////////
6272 // input adapters //
6273 ////////////////////
6274 
6275 #ifndef JSON_NO_IO
6276 /*! 
6277 Input adapter for stdio file access. This adapter read only 1 byte and do not use any 
6278  buffer. This adapter is a very low level adapter. 
6279 */
6280 class file_input_adapter
6281 {
6282   public:
6283     using char_type = char;
6284 
6285     JSON_HEDLEY_NON_NULL(2)
6286     explicit file_input_adapter(std::FILE* f) noexcept
6287         : m_file(f)
6288     {
6289         JSON_ASSERT(m_file != nullptr);
6290     }
6291 
6292     // make class move-only
6293     file_input_adapter(const file_input_adapter&) = delete;
6294     file_input_adapter(file_input_adapter&&) noexcept = default;
6295     file_input_adapter& operator=(const file_input_adapter&) = delete;
6296     file_input_adapter& operator=(file_input_adapter&&) = delete;
6297     ~file_input_adapter() = default;
6298 
6299     std::char_traits<char>::int_type get_character() noexcept
6300     {
6301         return std::fgetc(m_file);
6302     }
6303 
6304     // returns the number of characters successfully read
6305     template<class T>
6306     std::size_t get_elements(T* dest, std::size_t count = 1)
6307     {
6308         return fread(dest, 1, sizeof(T) * count, m_file);
6309     }
6310 
6311   private:
6312     /// the file pointer to read from
6313     std::FILE* m_file;
6314 };
6315 
6316 /*! 
6317 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at 
6318 beginning of input. Does not support changing the underlying std::streambuf 
6319 in mid-input. Maintains underlying std::istream and std::streambuf to support 
6320 subsequent use of standard std::istream operations to process any input 
6321 characters following those used in parsing the JSON input.  Clears the 
6322 std::istream flags; any input errors (e.g., EOF) will be detected by the first 
6323 subsequent call for input from the std::istream. 
6324 */
6325 class input_stream_adapter
6326 {
6327   public:
6328     using char_type = char;
6329 
6330     ~input_stream_adapter()
6331     {
6332         // clear stream flags; we use underlying streambuf I/O, do not
6333         // maintain ifstream flags, except eof
6334         if (is != nullptr)
6335         {
6336             is->clear(is->rdstate() & std::ios::eofbit);
6337         }
6338     }
6339 
6340     explicit input_stream_adapter(std::istream& i)
6341         : is(&i), sb(i.rdbuf())
6342     {}
6343 
6344     // delete because of pointer members
6345     input_stream_adapter(const input_stream_adapter&) = delete;
6346     input_stream_adapter& operator=(input_stream_adapter&) = delete;
6347     input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6348 
6349     input_stream_adapter(input_stream_adapter&& rhs) noexcept
6350         : is(rhs.is), sb(rhs.sb)
6351     {
6352         rhs.is = nullptr;
6353         rhs.sb = nullptr;
6354     }
6355 
6356     // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6357     // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6358     // end up as the same value, e.g. 0xFFFFFFFF.
6359     std::char_traits<char>::int_type get_character()
6360     {
6361         auto res = sb->sbumpc();
6362         // set eof manually, as we don't use the istream interface.
6363         if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6364         {
6365             is->clear(is->rdstate() | std::ios::eofbit);
6366         }
6367         return res;
6368     }
6369 
6370     template<class T>
6371     std::size_t get_elements(T* dest, std::size_t count = 1)
6372     {
6373         auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6374         if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6375         {
6376             is->clear(is->rdstate() | std::ios::eofbit);
6377         }
6378         return res;
6379     }
6380 
6381   private:
6382     /// the associated input stream
6383     std::istream* is = nullptr;
6384     std::streambuf* sb = nullptr;
6385 };
6386 #endif  // JSON_NO_IO
6387 
6388 // General-purpose iterator-based adapter. It might not be as fast as
6389 // theoretically possible for some containers, but it is extremely versatile.
6390 template<typename IteratorType>
6391 class iterator_input_adapter
6392 {
6393   public:
6394     using char_type = typename std::iterator_traits<IteratorType>::value_type;
6395 
6396     iterator_input_adapter(IteratorType first, IteratorType last)
6397         : current(std::move(first)), end(std::move(last))
6398     {}
6399 
6400     typename char_traits<char_type>::int_type get_character()
6401     {
6402         if (JSON_HEDLEY_LIKELY(current != end))
6403         {
6404             auto result = char_traits<char_type>::to_int_type(*current);
6405             std::advance(current, 1);
6406             return result;
6407         }
6408 
6409         return char_traits<char_type>::eof();
6410     }
6411 
6412     // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6413     template<class T>
6414     std::size_t get_elements(T* dest, std::size_t count = 1)
6415     {
6416         auto* ptr = reinterpret_cast<char*>(dest);
6417         for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6418         {
6419             if (JSON_HEDLEY_LIKELY(current != end))
6420             {
6421                 ptr[read_index] = static_cast<char>(*current);
6422                 std::advance(current, 1);
6423             }
6424             else
6425             {
6426                 return read_index;
6427             }
6428         }
6429         return count * sizeof(T);
6430     }
6431 
6432   private:
6433     IteratorType current;
6434     IteratorType end;
6435 
6436     template<typename BaseInputAdapter, size_t T>
6437     friend struct wide_string_input_helper;
6438 
6439     bool empty() const
6440     {
6441         return current == end;
6442     }
6443 };
6444 
6445 template<typename BaseInputAdapter, size_t T>
6446 struct wide_string_input_helper;
6447 
6448 template<typename BaseInputAdapter>
6449 struct wide_string_input_helper<BaseInputAdapter, 4>
6450 {
6451     // UTF-32
6452     static void fill_buffer(BaseInputAdapter& input,
6453                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6454                             size_t& utf8_bytes_index,
6455                             size_t& utf8_bytes_filled)
6456     {
6457         utf8_bytes_index = 0;
6458 
6459         if (JSON_HEDLEY_UNLIKELY(input.empty()))
6460         {
6461             utf8_bytes[0] = std::char_traits<char>::eof();
6462             utf8_bytes_filled = 1;
6463         }
6464         else
6465         {
6466             // get the current character
6467             const auto wc = input.get_character();
6468 
6469             // UTF-32 to UTF-8 encoding
6470             if (wc < 0x80)
6471             {
6472                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6473                 utf8_bytes_filled = 1;
6474             }
6475             else if (wc <= 0x7FF)
6476             {
6477                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6478                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6479                 utf8_bytes_filled = 2;
6480             }
6481             else if (wc <= 0xFFFF)
6482             {
6483                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6484                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6485                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6486                 utf8_bytes_filled = 3;
6487             }
6488             else if (wc <= 0x10FFFF)
6489             {
6490                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6491                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6492                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6493                 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6494                 utf8_bytes_filled = 4;
6495             }
6496             else
6497             {
6498                 // unknown character
6499                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6500                 utf8_bytes_filled = 1;
6501             }
6502         }
6503     }
6504 };
6505 
6506 template<typename BaseInputAdapter>
6507 struct wide_string_input_helper<BaseInputAdapter, 2>
6508 {
6509     // UTF-16
6510     static void fill_buffer(BaseInputAdapter& input,
6511                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6512                             size_t& utf8_bytes_index,
6513                             size_t& utf8_bytes_filled)
6514     {
6515         utf8_bytes_index = 0;
6516 
6517         if (JSON_HEDLEY_UNLIKELY(input.empty()))
6518         {
6519             utf8_bytes[0] = std::char_traits<char>::eof();
6520             utf8_bytes_filled = 1;
6521         }
6522         else
6523         {
6524             // get the current character
6525             const auto wc = input.get_character();
6526 
6527             // UTF-16 to UTF-8 encoding
6528             if (wc < 0x80)
6529             {
6530                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6531                 utf8_bytes_filled = 1;
6532             }
6533             else if (wc <= 0x7FF)
6534             {
6535                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6536                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6537                 utf8_bytes_filled = 2;
6538             }
6539             else if (0xD800 > wc || wc >= 0xE000)
6540             {
6541                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6542                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6543                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6544                 utf8_bytes_filled = 3;
6545             }
6546             else
6547             {
6548                 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6549                 {
6550                     const auto wc2 = static_cast<unsigned int>(input.get_character());
6551                     const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6552                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6553                     utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6554                     utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6555                     utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6556                     utf8_bytes_filled = 4;
6557                 }
6558                 else
6559                 {
6560                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6561                     utf8_bytes_filled = 1;
6562                 }
6563             }
6564         }
6565     }
6566 };
6567 
6568 // Wraps another input adapter to convert wide character types into individual bytes.
6569 template<typename BaseInputAdapter, typename WideCharType>
6570 class wide_string_input_adapter
6571 {
6572   public:
6573     using char_type = char;
6574 
6575     wide_string_input_adapter(BaseInputAdapter base)
6576         : base_adapter(base) {}
6577 
6578     typename std::char_traits<char>::int_type get_character() noexcept
6579     {
6580         // check if buffer needs to be filled
6581         if (utf8_bytes_index == utf8_bytes_filled)
6582         {
6583             fill_buffer<sizeof(WideCharType)>();
6584 
6585             JSON_ASSERT(utf8_bytes_filled > 0);
6586             JSON_ASSERT(utf8_bytes_index == 0);
6587         }
6588 
6589         // use buffer
6590         JSON_ASSERT(utf8_bytes_filled > 0);
6591         JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6592         return utf8_bytes[utf8_bytes_index++];
6593     }
6594 
6595     // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6596     template<class T>
6597     std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6598     {
6599         JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6600     }
6601 
6602   private:
6603     BaseInputAdapter base_adapter;
6604 
6605     template<size_t T>
6606     void fill_buffer()
6607     {
6608         wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6609     }
6610 
6611     /// a buffer for UTF-8 bytes
6612     std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6613 
6614     /// index to the utf8_codes array for the next valid byte
6615     std::size_t utf8_bytes_index = 0;
6616     /// number of valid bytes in the utf8_codes array
6617     std::size_t utf8_bytes_filled = 0;
6618 };
6619 
6620 template<typename IteratorType, typename Enable = void>
6621 struct iterator_input_adapter_factory
6622 {
6623     using iterator_type = IteratorType;
6624     using char_type = typename std::iterator_traits<iterator_type>::value_type;
6625     using adapter_type = iterator_input_adapter<iterator_type>;
6626 
6627     static adapter_type create(IteratorType first, IteratorType last)
6628     {
6629         return adapter_type(std::move(first), std::move(last));
6630     }
6631 };
6632 
6633 template<typename T>
6634 struct is_iterator_of_multibyte
6635 {
6636     using value_type = typename std::iterator_traits<T>::value_type;
6637     enum
6638     {
6639         value = sizeof(value_type) > 1
6640     };
6641 };
6642 
6643 template<typename IteratorType>
6644 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6645 {
6646     using iterator_type = IteratorType;
6647     using char_type = typename std::iterator_traits<iterator_type>::value_type;
6648     using base_adapter_type = iterator_input_adapter<iterator_type>;
6649     using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
6650 
6651     static adapter_type create(IteratorType first, IteratorType last)
6652     {
6653         return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6654     }
6655 };
6656 
6657 // General purpose iterator-based input
6658 template<typename IteratorType>
6659 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6660 {
6661     using factory_type = iterator_input_adapter_factory<IteratorType>;
6662     return factory_type::create(first, last);
6663 }
6664 
6665 // Convenience shorthand from container to iterator
6666 // Enables ADL on begin(container) and end(container)
6667 // Encloses the using declarations in namespace for not to leak them to outside scope
6668 
6669 namespace container_input_adapter_factory_impl
6670 {
6671 
6672 using std::begin;
6673 using std::end;
6674 
6675 template<typename ContainerType, typename Enable = void>
6676 struct container_input_adapter_factory {};
6677 
6678 template<typename ContainerType>
6679 struct container_input_adapter_factory< ContainerType,
6680        void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6681        {
6682            using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6683 
6684            static adapter_type create(const ContainerType& container)
6685 {
6686     return input_adapter(begin(container), end(container));
6687 }
6688        };
6689 
6690 }  // namespace container_input_adapter_factory_impl
6691 
6692 template<typename ContainerType>
6693 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
6694 {
6695     return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
6696 }
6697 
6698 #ifndef JSON_NO_IO
6699 // Special cases with fast paths
6700 inline file_input_adapter input_adapter(std::FILE* file)
6701 {
6702     if (file == nullptr)
6703     {
6704         JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6705     }
6706     return file_input_adapter(file);
6707 }
6708 
6709 inline input_stream_adapter input_adapter(std::istream& stream)
6710 {
6711     return input_stream_adapter(stream);
6712 }
6713 
6714 inline input_stream_adapter input_adapter(std::istream&& stream)
6715 {
6716     return input_stream_adapter(stream);
6717 }
6718 #endif  // JSON_NO_IO
6719 
6720 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6721 
6722 // Null-delimited strings, and the like.
6723 template < typename CharT,
6724            typename std::enable_if <
6725                std::is_pointer<CharT>::value&&
6726                !std::is_array<CharT>::value&&
6727                std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6728                sizeof(typename std::remove_pointer<CharT>::type) == 1,
6729                int >::type = 0 >
6730 contiguous_bytes_input_adapter input_adapter(CharT b)
6731 {
6732     if (b == nullptr)
6733     {
6734         JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6735     }
6736     auto length = std::strlen(reinterpret_cast<const char*>(b));
6737     const auto* ptr = reinterpret_cast<const char*>(b);
6738     return input_adapter(ptr, ptr + length);
6739 }
6740 
6741 template<typename T, std::size_t N>
6742 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6743 {
6744     return input_adapter(array, array + N);
6745 }
6746 
6747 // This class only handles inputs of input_buffer_adapter type.
6748 // It's required so that expressions like {ptr, len} can be implicitly cast
6749 // to the correct adapter.
6750 class span_input_adapter
6751 {
6752   public:
6753     template < typename CharT,
6754                typename std::enable_if <
6755                    std::is_pointer<CharT>::value&&
6756                    std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6757                    sizeof(typename std::remove_pointer<CharT>::type) == 1,
6758                    int >::type = 0 >
6759     span_input_adapter(CharT b, std::size_t l)
6760         : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6761 
6762     template<class IteratorType,
6763              typename std::enable_if<
6764                  std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6765                  int>::type = 0>
6766     span_input_adapter(IteratorType first, IteratorType last)
6767         : ia(input_adapter(first, last)) {}
6768 
6769     contiguous_bytes_input_adapter&& get()
6770     {
6771         return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6772     }
6773 
6774   private:
6775     contiguous_bytes_input_adapter ia;
6776 };
6777 
6778 }  // namespace detail
6779 NLOHMANN_JSON_NAMESPACE_END
6780 
6781 // #include <nlohmann/detail/input/json_sax.hpp>
6782 //     __ _____ _____ _____
6783 //  __|  |   __|     |   | |  JSON for Modern C++
6784 // |  |  |__   |  |  | | | |  version 3.11.3
6785 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
6786 //
6787 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
6788 // SPDX-License-Identifier: MIT
6789 
6790 
6791 
6792 #include <cstddef>
6793 #include <string> // string
6794 #include <utility> // move
6795 #include <vector> // vector
6796 
6797 // #include <nlohmann/detail/exceptions.hpp>
6798 
6799 // #include <nlohmann/detail/macro_scope.hpp>
6800 
6801 // #include <nlohmann/detail/string_concat.hpp>
6802 
6803 
6804 NLOHMANN_JSON_NAMESPACE_BEGIN
6805 
6806 /*! 
6807 @brief SAX interface 
6808  
6809 This class describes the SAX interface used by @ref nlohmann::json::sax_parse. 
6810 Each function is called in different situations while the input is parsed. The 
6811 boolean return value informs the parser whether to continue processing the 
6812 input. 
6813 */
6814 template<typename BasicJsonType>
6815 struct json_sax
6816 {
6817     using number_integer_t = typename BasicJsonType::number_integer_t;
6818     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6819     using number_float_t = typename BasicJsonType::number_float_t;
6820     using string_t = typename BasicJsonType::string_t;
6821     using binary_t = typename BasicJsonType::binary_t;
6822 
6823     /*! 
6824     @brief a null value was read 
6825     @return whether parsing should proceed 
6826     */
6827     virtual bool null() = 0;
6828 
6829     /*! 
6830     @brief a boolean value was read 
6831     @param[in] val  boolean value 
6832     @return whether parsing should proceed 
6833     */
6834     virtual bool boolean(bool val) = 0;
6835 
6836     /*! 
6837     @brief an integer number was read 
6838     @param[in] val  integer value 
6839     @return whether parsing should proceed 
6840     */
6841     virtual bool number_integer(number_integer_t val) = 0;
6842 
6843     /*! 
6844     @brief an unsigned integer number was read 
6845     @param[in] val  unsigned integer value 
6846     @return whether parsing should proceed 
6847     */
6848     virtual bool number_unsigned(number_unsigned_t val) = 0;
6849 
6850     /*! 
6851     @brief a floating-point number was read 
6852     @param[in] val  floating-point value 
6853     @param[in] s    raw token value 
6854     @return whether parsing should proceed 
6855     */
6856     virtual bool number_float(number_float_t val, const string_t& s) = 0;
6857 
6858     /*! 
6859     @brief a string value was read 
6860     @param[in] val  string value 
6861     @return whether parsing should proceed 
6862     @note It is safe to move the passed string value. 
6863     */
6864     virtual bool string(string_t& val) = 0;
6865 
6866     /*! 
6867     @brief a binary value was read 
6868     @param[in] val  binary value 
6869     @return whether parsing should proceed 
6870     @note It is safe to move the passed binary value. 
6871     */
6872     virtual bool binary(binary_t& val) = 0;
6873 
6874     /*! 
6875     @brief the beginning of an object was read 
6876     @param[in] elements  number of object elements or -1 if unknown 
6877     @return whether parsing should proceed 
6878     @note binary formats may report the number of elements 
6879     */
6880     virtual bool start_object(std::size_t elements) = 0;
6881 
6882     /*! 
6883     @brief an object key was read 
6884     @param[in] val  object key 
6885     @return whether parsing should proceed 
6886     @note It is safe to move the passed string. 
6887     */
6888     virtual bool key(string_t& val) = 0;
6889 
6890     /*! 
6891     @brief the end of an object was read 
6892     @return whether parsing should proceed 
6893     */
6894     virtual bool end_object() = 0;
6895 
6896     /*! 
6897     @brief the beginning of an array was read 
6898     @param[in] elements  number of array elements or -1 if unknown 
6899     @return whether parsing should proceed 
6900     @note binary formats may report the number of elements 
6901     */
6902     virtual bool start_array(std::size_t elements) = 0;
6903 
6904     /*! 
6905     @brief the end of an array was read 
6906     @return whether parsing should proceed 
6907     */
6908     virtual bool end_array() = 0;
6909 
6910     /*! 
6911     @brief a parse error occurred 
6912     @param[in] position    the position in the input where the error occurs 
6913     @param[in] last_token  the last read token 
6914     @param[in] ex          an exception object describing the error 
6915     @return whether parsing should proceed (must return false) 
6916     */
6917     virtual bool parse_error(std::size_t position,
6918                              const std::string& last_token,
6919                              const detail::exception& ex) = 0;
6920 
6921     json_sax() = default;
6922     json_sax(const json_sax&) = default;
6923     json_sax(json_sax&&) noexcept = default;
6924     json_sax& operator=(const json_sax&) = default;
6925     json_sax& operator=(json_sax&&) noexcept = default;
6926     virtual ~json_sax() = default;
6927 };
6928 
6929 namespace detail
6930 {
6931 /*! 
6932 @brief SAX implementation to create a JSON value from SAX events 
6933  
6934 This class implements the @ref json_sax interface and processes the SAX events 
6935 to create a JSON value which makes it basically a DOM parser. The structure or 
6936 hierarchy of the JSON value is managed by the stack `ref_stack` which contains 
6937 a pointer to the respective array or object for each recursion depth. 
6938  
6939 After successful parsing, the value that is passed by reference to the 
6940 constructor contains the parsed value. 
6941  
6942 @tparam BasicJsonType  the JSON type 
6943 */
6944 template<typename BasicJsonType>
6945 class json_sax_dom_parser
6946 {
6947   public:
6948     using number_integer_t = typename BasicJsonType::number_integer_t;
6949     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6950     using number_float_t = typename BasicJsonType::number_float_t;
6951     using string_t = typename BasicJsonType::string_t;
6952     using binary_t = typename BasicJsonType::binary_t;
6953 
6954     /*! 
6955     @param[in,out] r  reference to a JSON value that is manipulated while 
6956                        parsing 
6957     @param[in] allow_exceptions_  whether parse errors yield exceptions 
6958     */
6959     explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6960         : root(r), allow_exceptions(allow_exceptions_)
6961     {}
6962 
6963     // make class move-only
6964     json_sax_dom_parser(const json_sax_dom_parser&) = delete;
6965     json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6966     json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6967     json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6968     ~json_sax_dom_parser() = default;
6969 
6970     bool null()
6971     {
6972         handle_value(nullptr);
6973         return true;
6974     }
6975 
6976     bool boolean(bool val)
6977     {
6978         handle_value(val);
6979         return true;
6980     }
6981 
6982     bool number_integer(number_integer_t val)
6983     {
6984         handle_value(val);
6985         return true;
6986     }
6987 
6988     bool number_unsigned(number_unsigned_t val)
6989     {
6990         handle_value(val);
6991         return true;
6992     }
6993 
6994     bool number_float(number_float_t val, const string_t& /*unused*/)
6995     {
6996         handle_value(val);
6997         return true;
6998     }
6999 
7000     bool string(string_t& val)
7001     {
7002         handle_value(val);
7003         return true;
7004     }
7005 
7006     bool binary(binary_t& val)
7007     {
7008         handle_value(std::move(val));
7009         return true;
7010     }
7011 
7012     bool start_object(std::size_t len)
7013     {
7014         ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
7015 
7016         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7017         {
7018             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7019         }
7020 
7021         return true;
7022     }
7023 
7024     bool key(string_t& val)
7025     {
7026         JSON_ASSERT(!ref_stack.empty());
7027         JSON_ASSERT(ref_stack.back()->is_object());
7028 
7029         // add null at given key and store the reference for later
7030         object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
7031         return true;
7032     }
7033 
7034     bool end_object()
7035     {
7036         JSON_ASSERT(!ref_stack.empty());
7037         JSON_ASSERT(ref_stack.back()->is_object());
7038 
7039         ref_stack.back()->set_parents();
7040         ref_stack.pop_back();
7041         return true;
7042     }
7043 
7044     bool start_array(std::size_t len)
7045     {
7046         ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
7047 
7048         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7049         {
7050             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7051         }
7052 
7053         return true;
7054     }
7055 
7056     bool end_array()
7057     {
7058         JSON_ASSERT(!ref_stack.empty());
7059         JSON_ASSERT(ref_stack.back()->is_array());
7060 
7061         ref_stack.back()->set_parents();
7062         ref_stack.pop_back();
7063         return true;
7064     }
7065 
7066     template<class Exception>
7067     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7068                      const Exception& ex)
7069     {
7070         errored = true;
7071         static_cast<void>(ex);
7072         if (allow_exceptions)
7073         {
7074             JSON_THROW(ex);
7075         }
7076         return false;
7077     }
7078 
7079     constexpr bool is_errored() const
7080     {
7081         return errored;
7082     }
7083 
7084   private:
7085     /*! 
7086     @invariant If the ref stack is empty, then the passed value will be the new 
7087                root. 
7088     @invariant If the ref stack contains a value, then it is an array or an 
7089                object to which we can add elements 
7090     */
7091     template<typename Value>
7092     JSON_HEDLEY_RETURNS_NON_NULL
7093     BasicJsonType* handle_value(Value&& v)
7094     {
7095         if (ref_stack.empty())
7096         {
7097             root = BasicJsonType(std::forward<Value>(v));
7098             return &root;
7099         }
7100 
7101         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7102 
7103         if (ref_stack.back()->is_array())
7104         {
7105             ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
7106             return &(ref_stack.back()->m_data.m_value.array->back());
7107         }
7108 
7109         JSON_ASSERT(ref_stack.back()->is_object());
7110         JSON_ASSERT(object_element);
7111         *object_element = BasicJsonType(std::forward<Value>(v));
7112         return object_element;
7113     }
7114 
7115     /// the parsed JSON value
7116     BasicJsonType& root;
7117     /// stack to model hierarchy of values
7118     std::vector<BasicJsonType*> ref_stack {};
7119     /// helper to hold the reference for the next object element
7120     BasicJsonType* object_element = nullptr;
7121     /// whether a syntax error occurred
7122     bool errored = false;
7123     /// whether to throw exceptions in case of errors
7124     const bool allow_exceptions = true;
7125 };
7126 
7127 template<typename BasicJsonType>
7128 class json_sax_dom_callback_parser
7129 {
7130   public:
7131     using number_integer_t = typename BasicJsonType::number_integer_t;
7132     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7133     using number_float_t = typename BasicJsonType::number_float_t;
7134     using string_t = typename BasicJsonType::string_t;
7135     using binary_t = typename BasicJsonType::binary_t;
7136     using parser_callback_t = typename BasicJsonType::parser_callback_t;
7137     using parse_event_t = typename BasicJsonType::parse_event_t;
7138 
7139     json_sax_dom_callback_parser(BasicJsonType& r,
7140                                  parser_callback_t cb,
7141                                  const bool allow_exceptions_ = true)
7142         : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_)
7143     {
7144         keep_stack.push_back(true);
7145     }
7146 
7147     // make class move-only
7148     json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
7149     json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7150     json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
7151     json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7152     ~json_sax_dom_callback_parser() = default;
7153 
7154     bool null()
7155     {
7156         handle_value(nullptr);
7157         return true;
7158     }
7159 
7160     bool boolean(bool val)
7161     {
7162         handle_value(val);
7163         return true;
7164     }
7165 
7166     bool number_integer(number_integer_t val)
7167     {
7168         handle_value(val);
7169         return true;
7170     }
7171 
7172     bool number_unsigned(number_unsigned_t val)
7173     {
7174         handle_value(val);
7175         return true;
7176     }
7177 
7178     bool number_float(number_float_t val, const string_t& /*unused*/)
7179     {
7180         handle_value(val);
7181         return true;
7182     }
7183 
7184     bool string(string_t& val)
7185     {
7186         handle_value(val);
7187         return true;
7188     }
7189 
7190     bool binary(binary_t& val)
7191     {
7192         handle_value(std::move(val));
7193         return true;
7194     }
7195 
7196     bool start_object(std::size_t len)
7197     {
7198         // check callback for object start
7199         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7200         keep_stack.push_back(keep);
7201 
7202         auto val = handle_value(BasicJsonType::value_t::object, true);
7203         ref_stack.push_back(val.second);
7204 
7205         // check object limit
7206         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7207         {
7208             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7209         }
7210 
7211         return true;
7212     }
7213 
7214     bool key(string_t& val)
7215     {
7216         BasicJsonType k = BasicJsonType(val);
7217 
7218         // check callback for key
7219         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7220         key_keep_stack.push_back(keep);
7221 
7222         // add discarded value at given key and store the reference for later
7223         if (keep && ref_stack.back())
7224         {
7225             object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7226         }
7227 
7228         return true;
7229     }
7230 
7231     bool end_object()
7232     {
7233         if (ref_stack.back())
7234         {
7235             if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7236             {
7237                 // discard object
7238                 *ref_stack.back() = discarded;
7239             }
7240             else
7241             {
7242                 ref_stack.back()->set_parents();
7243             }
7244         }
7245 
7246         JSON_ASSERT(!ref_stack.empty());
7247         JSON_ASSERT(!keep_stack.empty());
7248         ref_stack.pop_back();
7249         keep_stack.pop_back();
7250 
7251         if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7252         {
7253             // remove discarded value
7254             for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7255             {
7256                 if (it->is_discarded())
7257                 {
7258                     ref_stack.back()->erase(it);
7259                     break;
7260                 }
7261             }
7262         }
7263 
7264         return true;
7265     }
7266 
7267     bool start_array(std::size_t len)
7268     {
7269         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7270         keep_stack.push_back(keep);
7271 
7272         auto val = handle_value(BasicJsonType::value_t::array, true);
7273         ref_stack.push_back(val.second);
7274 
7275         // check array limit
7276         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7277         {
7278             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7279         }
7280 
7281         return true;
7282     }
7283 
7284     bool end_array()
7285     {
7286         bool keep = true;
7287 
7288         if (ref_stack.back())
7289         {
7290             keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7291             if (keep)
7292             {
7293                 ref_stack.back()->set_parents();
7294             }
7295             else
7296             {
7297                 // discard array
7298                 *ref_stack.back() = discarded;
7299             }
7300         }
7301 
7302         JSON_ASSERT(!ref_stack.empty());
7303         JSON_ASSERT(!keep_stack.empty());
7304         ref_stack.pop_back();
7305         keep_stack.pop_back();
7306 
7307         // remove discarded value
7308         if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7309         {
7310             ref_stack.back()->m_data.m_value.array->pop_back();
7311         }
7312 
7313         return true;
7314     }
7315 
7316     template<class Exception>
7317     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7318                      const Exception& ex)
7319     {
7320         errored = true;
7321         static_cast<void>(ex);
7322         if (allow_exceptions)
7323         {
7324             JSON_THROW(ex);
7325         }
7326         return false;
7327     }
7328 
7329     constexpr bool is_errored() const
7330     {
7331         return errored;
7332     }
7333 
7334   private:
7335     /*! 
7336     @param[in] v  value to add to the JSON value we build during parsing 
7337     @param[in] skip_callback  whether we should skip calling the callback 
7338                function; this is required after start_array() and 
7339                start_object() SAX events, because otherwise we would call the 
7340                callback function with an empty array or object, respectively. 
7341  
7342     @invariant If the ref stack is empty, then the passed value will be the new 
7343                root. 
7344     @invariant If the ref stack contains a value, then it is an array or an 
7345                object to which we can add elements 
7346  
7347     @return pair of boolean (whether value should be kept) and pointer (to the 
7348             passed value in the ref_stack hierarchy; nullptr if not kept) 
7349     */
7350     template<typename Value>
7351     std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7352     {
7353         JSON_ASSERT(!keep_stack.empty());
7354 
7355         // do not handle this value if we know it would be added to a discarded
7356         // container
7357         if (!keep_stack.back())
7358         {
7359             return {false, nullptr};
7360         }
7361 
7362         // create value
7363         auto value = BasicJsonType(std::forward<Value>(v));
7364 
7365         // check callback
7366         const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7367 
7368         // do not handle this value if we just learnt it shall be discarded
7369         if (!keep)
7370         {
7371             return {false, nullptr};
7372         }
7373 
7374         if (ref_stack.empty())
7375         {
7376             root = std::move(value);
7377             return {true, & root};
7378         }
7379 
7380         // skip this value if we already decided to skip the parent
7381         // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7382         if (!ref_stack.back())
7383         {
7384             return {false, nullptr};
7385         }
7386 
7387         // we now only expect arrays and objects
7388         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7389 
7390         // array
7391         if (ref_stack.back()->is_array())
7392         {
7393             ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7394             return {true, & (ref_stack.back()->m_data.m_value.array->back())};
7395         }
7396 
7397         // object
7398         JSON_ASSERT(ref_stack.back()->is_object());
7399         // check if we should store an element for the current key
7400         JSON_ASSERT(!key_keep_stack.empty());
7401         const bool store_element = key_keep_stack.back();
7402         key_keep_stack.pop_back();
7403 
7404         if (!store_element)
7405         {
7406             return {false, nullptr};
7407         }
7408 
7409         JSON_ASSERT(object_element);
7410         *object_element = std::move(value);
7411         return {true, object_element};
7412     }
7413 
7414     /// the parsed JSON value
7415     BasicJsonType& root;
7416     /// stack to model hierarchy of values
7417     std::vector<BasicJsonType*> ref_stack {};
7418     /// stack to manage which values to keep
7419     std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
7420     /// stack to manage which object keys to keep
7421     std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
7422     /// helper to hold the reference for the next object element
7423     BasicJsonType* object_element = nullptr;
7424     /// whether a syntax error occurred
7425     bool errored = false;
7426     /// callback function
7427     const parser_callback_t callback = nullptr;
7428     /// whether to throw exceptions in case of errors
7429     const bool allow_exceptions = true;
7430     /// a discarded value for the callback
7431     BasicJsonType discarded = BasicJsonType::value_t::discarded;
7432 };
7433 
7434 template<typename BasicJsonType>
7435 class json_sax_acceptor
7436 {
7437   public:
7438     using number_integer_t = typename BasicJsonType::number_integer_t;
7439     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7440     using number_float_t = typename BasicJsonType::number_float_t;
7441     using string_t = typename BasicJsonType::string_t;
7442     using binary_t = typename BasicJsonType::binary_t;
7443 
7444     bool null()
7445     {
7446         return true;
7447     }
7448 
7449     bool boolean(bool /*unused*/)
7450     {
7451         return true;
7452     }
7453 
7454     bool number_integer(number_integer_t /*unused*/)
7455     {
7456         return true;
7457     }
7458 
7459     bool number_unsigned(number_unsigned_t /*unused*/)
7460     {
7461         return true;
7462     }
7463 
7464     bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7465     {
7466         return true;
7467     }
7468 
7469     bool string(string_t& /*unused*/)
7470     {
7471         return true;
7472     }
7473 
7474     bool binary(binary_t& /*unused*/)
7475     {
7476         return true;
7477     }
7478 
7479     bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7480     {
7481         return true;
7482     }
7483 
7484     bool key(string_t& /*unused*/)
7485     {
7486         return true;
7487     }
7488 
7489     bool end_object()
7490     {
7491         return true;
7492     }
7493 
7494     bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7495     {
7496         return true;
7497     }
7498 
7499     bool end_array()
7500     {
7501         return true;
7502     }
7503 
7504     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7505     {
7506         return false;
7507     }
7508 };
7509 
7510 }  // namespace detail
7511 NLOHMANN_JSON_NAMESPACE_END
7512 
7513 // #include <nlohmann/detail/input/lexer.hpp>
7514 //     __ _____ _____ _____
7515 //  __|  |   __|     |   | |  JSON for Modern C++
7516 // |  |  |__   |  |  | | | |  version 3.11.3
7517 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
7518 //
7519 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
7520 // SPDX-License-Identifier: MIT
7521 
7522 
7523 
7524 #include <array> // array
7525 #include <clocale> // localeconv
7526 #include <cstddef> // size_t
7527 #include <cstdio> // snprintf
7528 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7529 #include <initializer_list> // initializer_list
7530 #include <string> // char_traits, string
7531 #include <utility> // move
7532 #include <vector> // vector
7533 
7534 // #include <nlohmann/detail/input/input_adapters.hpp>
7535 
7536 // #include <nlohmann/detail/input/position_t.hpp>
7537 
7538 // #include <nlohmann/detail/macro_scope.hpp>
7539 
7540 // #include <nlohmann/detail/meta/type_traits.hpp>
7541 
7542 
7543 NLOHMANN_JSON_NAMESPACE_BEGIN
7544 namespace detail
7545 {
7546 
7547 ///////////
7548 // lexer //
7549 ///////////
7550 
7551 template<typename BasicJsonType>
7552 class lexer_base
7553 {
7554   public:
7555     /// token types for the parser
7556     enum class token_type
7557     {
7558         uninitialized,    ///< indicating the scanner is uninitialized
7559         literal_true,     ///< the `true` literal
7560         literal_false,    ///< the `false` literal
7561         literal_null,     ///< the `null` literal
7562         value_string,     ///< a string -- use get_string() for actual value
7563         value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
7564         value_integer,    ///< a signed integer -- use get_number_integer() for actual value
7565         value_float,      ///< an floating point number -- use get_number_float() for actual value
7566         begin_array,      ///< the character for array begin `[`
7567         begin_object,     ///< the character for object begin `{`
7568         end_array,        ///< the character for array end `]`
7569         end_object,       ///< the character for object end `}`
7570         name_separator,   ///< the name separator `:`
7571         value_separator,  ///< the value separator `,`
7572         parse_error,      ///< indicating a parse error
7573         end_of_input,     ///< indicating the end of the input buffer
7574         literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
7575     };
7576 
7577     /// return name of values of type token_type (only used for errors)
7578     JSON_HEDLEY_RETURNS_NON_NULL
7579     JSON_HEDLEY_CONST
7580     static const char* token_type_name(const token_type t) noexcept
7581     {
7582         switch (t)
7583         {
7584             case token_type::uninitialized:
7585                 return "<uninitialized>";
7586             case token_type::literal_true:
7587                 return "true literal";
7588             case token_type::literal_false:
7589                 return "false literal";
7590             case token_type::literal_null:
7591                 return "null literal";
7592             case token_type::value_string:
7593                 return "string literal";
7594             case token_type::value_unsigned:
7595             case token_type::value_integer:
7596             case token_type::value_float:
7597                 return "number literal";
7598             case token_type::begin_array:
7599                 return "'['";
7600             case token_type::begin_object:
7601                 return "'{'";
7602             case token_type::end_array:
7603                 return "']'";
7604             case token_type::end_object:
7605                 return "'}'";
7606             case token_type::name_separator:
7607                 return "':'";
7608             case token_type::value_separator:
7609                 return "','";
7610             case token_type::parse_error:
7611                 return "<parse error>";
7612             case token_type::end_of_input:
7613                 return "end of input";
7614             case token_type::literal_or_value:
7615                 return "'[', '{', or a literal";
7616             // LCOV_EXCL_START
7617             default: // catch non-enum values
7618                 return "unknown token";
7619                 // LCOV_EXCL_STOP
7620         }
7621     }
7622 };
7623 /*! 
7624 @brief lexical analysis 
7625  
7626 This class organizes the lexical analysis during JSON deserialization. 
7627 */
7628 template<typename BasicJsonType, typename InputAdapterType>
7629 class lexer : public lexer_base<BasicJsonType>
7630 {
7631     using number_integer_t = typename BasicJsonType::number_integer_t;
7632     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7633     using number_float_t = typename BasicJsonType::number_float_t;
7634     using string_t = typename BasicJsonType::string_t;
7635     using char_type = typename InputAdapterType::char_type;
7636     using char_int_type = typename char_traits<char_type>::int_type;
7637 
7638   public:
7639     using token_type = typename lexer_base<BasicJsonType>::token_type;
7640 
7641     explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7642         : ia(std::move(adapter))
7643         , ignore_comments(ignore_comments_)
7644         , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7645     {}
7646 
7647     // delete because of pointer members
7648     lexer(const lexer&) = delete;
7649     lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7650     lexer& operator=(lexer&) = delete;
7651     lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7652     ~lexer() = default;
7653 
7654   private:
7655     /////////////////////
7656     // locales
7657     /////////////////////
7658 
7659     /// return the locale-dependent decimal point
7660     JSON_HEDLEY_PURE
7661     static char get_decimal_point() noexcept
7662     {
7663         const auto* loc = localeconv();
7664         JSON_ASSERT(loc != nullptr);
7665         return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7666     }
7667 
7668     /////////////////////
7669     // scan functions
7670     /////////////////////
7671 
7672     /*! 
7673     @brief get codepoint from 4 hex characters following `\u` 
7674  
7675     For input "\u c1 c2 c3 c4" the codepoint is: 
7676       (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 
7677     = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) 
7678  
7679     Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' 
7680     must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The 
7681     conversion is done by subtracting the offset (0x30, 0x37, and 0x57) 
7682     between the ASCII value of the character and the desired integer value. 
7683  
7684     @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or 
7685             non-hex character) 
7686     */
7687     int get_codepoint()
7688     {
7689         // this function only makes sense after reading `\u`
7690         JSON_ASSERT(current == 'u');
7691         int codepoint = 0;
7692 
7693         const auto factors = { 12u, 8u, 4u, 0u };
7694         for (const auto factor : factors)
7695         {
7696             get();
7697 
7698             if (current >= '0' && current <= '9')
7699             {
7700                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7701             }
7702             else if (current >= 'A' && current <= 'F')
7703             {
7704                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7705             }
7706             else if (current >= 'a' && current <= 'f')
7707             {
7708                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7709             }
7710             else
7711             {
7712                 return -1;
7713             }
7714         }
7715 
7716         JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7717         return codepoint;
7718     }
7719 
7720     /*! 
7721     @brief check if the next byte(s) are inside a given range 
7722  
7723     Adds the current byte and, for each passed range, reads a new byte and 
7724     checks if it is inside the range. If a violation was detected, set up an 
7725     error message and return false. Otherwise, return true. 
7726  
7727     @param[in] ranges  list of integers; interpreted as list of pairs of 
7728                        inclusive lower and upper bound, respectively 
7729  
7730     @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, 
7731          1, 2, or 3 pairs. This precondition is enforced by an assertion. 
7732  
7733     @return true if and only if no range violation was detected 
7734     */
7735     bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7736     {
7737         JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7738         add(current);
7739 
7740         for (auto range = ranges.begin(); range != ranges.end(); ++range)
7741         {
7742             get();
7743             if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7744             {
7745                 add(current);
7746             }
7747             else
7748             {
7749                 error_message = "invalid string: ill-formed UTF-8 byte";
7750                 return false;
7751             }
7752         }
7753 
7754         return true;
7755     }
7756 
7757     /*! 
7758     @brief scan a string literal 
7759  
7760     This function scans a string according to Sect. 7 of RFC 8259. While 
7761     scanning, bytes are escaped and copied into buffer token_buffer. Then the 
7762     function returns successfully, token_buffer is *not* null-terminated (as it 
7763     may contain \0 bytes), and token_buffer.size() is the number of bytes in the 
7764     string. 
7765  
7766     @return token_type::value_string if string could be successfully scanned, 
7767             token_type::parse_error otherwise 
7768  
7769     @note In case of errors, variable error_message contains a textual 
7770           description. 
7771     */
7772     token_type scan_string()
7773     {
7774         // reset token_buffer (ignore opening quote)
7775         reset();
7776 
7777         // we entered the function by reading an open quote
7778         JSON_ASSERT(current == '\"');
7779 
7780         while (true)
7781         {
7782             // get next character
7783             switch (get())
7784             {
7785                 // end of file while parsing string
7786                 case char_traits<char_type>::eof():
7787                 {
7788                     error_message = "invalid string: missing closing quote";
7789                     return token_type::parse_error;
7790                 }
7791 
7792                 // closing quote
7793                 case '\"':
7794                 {
7795                     return token_type::value_string;
7796                 }
7797 
7798                 // escapes
7799                 case '\\':
7800                 {
7801                     switch (get())
7802                     {
7803                         // quotation mark
7804                         case '\"':
7805                             add('\"');
7806                             break;
7807                         // reverse solidus
7808                         case '\\':
7809                             add('\\');
7810                             break;
7811                         // solidus
7812                         case '/':
7813                             add('/');
7814                             break;
7815                         // backspace
7816                         case 'b':
7817                             add('\b');
7818                             break;
7819                         // form feed
7820                         case 'f':
7821                             add('\f');
7822                             break;
7823                         // line feed
7824                         case 'n':
7825                             add('\n');
7826                             break;
7827                         // carriage return
7828                         case 'r':
7829                             add('\r');
7830                             break;
7831                         // tab
7832                         case 't':
7833                             add('\t');
7834                             break;
7835 
7836                         // unicode escapes
7837                         case 'u':
7838                         {
7839                             const int codepoint1 = get_codepoint();
7840                             int codepoint = codepoint1; // start with codepoint1
7841 
7842                             if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7843                             {
7844                                 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7845                                 return token_type::parse_error;
7846                             }
7847 
7848                             // check if code point is a high surrogate
7849                             if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7850                             {
7851                                 // expect next \uxxxx entry
7852                                 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7853                                 {
7854                                     const int codepoint2 = get_codepoint();
7855 
7856                                     if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7857                                     {
7858                                         error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7859                                         return token_type::parse_error;
7860                                     }
7861 
7862                                     // check if codepoint2 is a low surrogate
7863                                     if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7864                                     {
7865                                         // overwrite codepoint
7866                                         codepoint = static_cast<int>(
7867                                                         // high surrogate occupies the most significant 22 bits
7868                                                         (static_cast<unsigned int>(codepoint1) << 10u)
7869                                                         // low surrogate occupies the least significant 15 bits
7870                                                         + static_cast<unsigned int>(codepoint2)
7871                                                         // there is still the 0xD800, 0xDC00 and 0x10000 noise
7872                                                         // in the result, so we have to subtract with:
7873                                                         // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7874                                                         - 0x35FDC00u);
7875                                     }
7876                                     else
7877                                     {
7878                                         error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7879                                         return token_type::parse_error;
7880                                     }
7881                                 }
7882                                 else
7883                                 {
7884                                     error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7885                                     return token_type::parse_error;
7886                                 }
7887                             }
7888                             else
7889                             {
7890                                 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7891                                 {
7892                                     error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7893                                     return token_type::parse_error;
7894                                 }
7895                             }
7896 
7897                             // result of the above calculation yields a proper codepoint
7898                             JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7899 
7900                             // translate codepoint into bytes
7901                             if (codepoint < 0x80)
7902                             {
7903                                 // 1-byte characters: 0xxxxxxx (ASCII)
7904                                 add(static_cast<char_int_type>(codepoint));
7905                             }
7906                             else if (codepoint <= 0x7FF)
7907                             {
7908                                 // 2-byte characters: 110xxxxx 10xxxxxx
7909                                 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7910                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7911                             }
7912                             else if (codepoint <= 0xFFFF)
7913                             {
7914                                 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7915                                 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7916                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7917                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7918                             }
7919                             else
7920                             {
7921                                 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7922                                 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7923                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7924                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7925                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7926                             }
7927 
7928                             break;
7929                         }
7930 
7931                         // other characters after escape
7932                         default:
7933                             error_message = "invalid string: forbidden character after backslash";
7934                             return token_type::parse_error;
7935                     }
7936 
7937                     break;
7938                 }
7939 
7940                 // invalid control characters
7941                 case 0x00:
7942                 {
7943                     error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7944                     return token_type::parse_error;
7945                 }
7946 
7947                 case 0x01:
7948                 {
7949                     error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7950                     return token_type::parse_error;
7951                 }
7952 
7953                 case 0x02:
7954                 {
7955                     error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7956                     return token_type::parse_error;
7957                 }
7958 
7959                 case 0x03:
7960                 {
7961                     error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7962                     return token_type::parse_error;
7963                 }
7964 
7965                 case 0x04:
7966                 {
7967                     error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7968                     return token_type::parse_error;
7969                 }
7970 
7971                 case 0x05:
7972                 {
7973                     error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7974                     return token_type::parse_error;
7975                 }
7976 
7977                 case 0x06:
7978                 {
7979                     error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7980                     return token_type::parse_error;
7981                 }
7982 
7983                 case 0x07:
7984                 {
7985                     error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7986                     return token_type::parse_error;
7987                 }
7988 
7989                 case 0x08:
7990                 {
7991                     error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7992                     return token_type::parse_error;
7993                 }
7994 
7995                 case 0x09:
7996                 {
7997                     error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7998                     return token_type::parse_error;
7999                 }
8000 
8001                 case 0x0A:
8002                 {
8003                     error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
8004                     return token_type::parse_error;
8005                 }
8006 
8007                 case 0x0B:
8008                 {
8009                     error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
8010                     return token_type::parse_error;
8011                 }
8012 
8013                 case 0x0C:
8014                 {
8015                     error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
8016                     return token_type::parse_error;
8017                 }
8018 
8019                 case 0x0D:
8020                 {
8021                     error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
8022                     return token_type::parse_error;
8023                 }
8024 
8025                 case 0x0E:
8026                 {
8027                     error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
8028                     return token_type::parse_error;
8029                 }
8030 
8031                 case 0x0F:
8032                 {
8033                     error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
8034                     return token_type::parse_error;
8035                 }
8036 
8037                 case 0x10:
8038                 {
8039                     error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
8040                     return token_type::parse_error;
8041                 }
8042 
8043                 case 0x11:
8044                 {
8045                     error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
8046                     return token_type::parse_error;
8047                 }
8048 
8049                 case 0x12:
8050                 {
8051                     error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
8052                     return token_type::parse_error;
8053                 }
8054 
8055                 case 0x13:
8056                 {
8057                     error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
8058                     return token_type::parse_error;
8059                 }
8060 
8061                 case 0x14:
8062                 {
8063                     error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
8064                     return token_type::parse_error;
8065                 }
8066 
8067                 case 0x15:
8068                 {
8069                     error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
8070                     return token_type::parse_error;
8071                 }
8072 
8073                 case 0x16:
8074                 {
8075                     error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
8076                     return token_type::parse_error;
8077                 }
8078 
8079                 case 0x17:
8080                 {
8081                     error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
8082                     return token_type::parse_error;
8083                 }
8084 
8085                 case 0x18:
8086                 {
8087                     error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
8088                     return token_type::parse_error;
8089                 }
8090 
8091                 case 0x19:
8092                 {
8093                     error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
8094                     return token_type::parse_error;
8095                 }
8096 
8097                 case 0x1A:
8098                 {
8099                     error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
8100                     return token_type::parse_error;
8101                 }
8102 
8103                 case 0x1B:
8104                 {
8105                     error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
8106                     return token_type::parse_error;
8107                 }
8108 
8109                 case 0x1C:
8110                 {
8111                     error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
8112                     return token_type::parse_error;
8113                 }
8114 
8115                 case 0x1D:
8116                 {
8117                     error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
8118                     return token_type::parse_error;
8119                 }
8120 
8121                 case 0x1E:
8122                 {
8123                     error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
8124                     return token_type::parse_error;
8125                 }
8126 
8127                 case 0x1F:
8128                 {
8129                     error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
8130                     return token_type::parse_error;
8131                 }
8132 
8133                 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
8134                 case 0x20:
8135                 case 0x21:
8136                 case 0x23:
8137                 case 0x24:
8138                 case 0x25:
8139                 case 0x26:
8140                 case 0x27:
8141                 case 0x28:
8142                 case 0x29:
8143                 case 0x2A:
8144                 case 0x2B:
8145                 case 0x2C:
8146                 case 0x2D:
8147                 case 0x2E:
8148                 case 0x2F:
8149                 case 0x30:
8150                 case 0x31:
8151                 case 0x32:
8152                 case 0x33:
8153                 case 0x34:
8154                 case 0x35:
8155                 case 0x36:
8156                 case 0x37:
8157                 case 0x38:
8158                 case 0x39:
8159                 case 0x3A:
8160                 case 0x3B:
8161                 case 0x3C:
8162                 case 0x3D:
8163                 case 0x3E:
8164                 case 0x3F:
8165                 case 0x40:
8166                 case 0x41:
8167                 case 0x42:
8168                 case 0x43:
8169                 case 0x44:
8170                 case 0x45:
8171                 case 0x46:
8172                 case 0x47:
8173                 case 0x48:
8174                 case 0x49:
8175                 case 0x4A:
8176                 case 0x4B:
8177                 case 0x4C:
8178                 case 0x4D:
8179                 case 0x4E:
8180                 case 0x4F:
8181                 case 0x50:
8182                 case 0x51:
8183                 case 0x52:
8184                 case 0x53:
8185                 case 0x54:
8186                 case 0x55:
8187                 case 0x56:
8188                 case 0x57:
8189                 case 0x58:
8190                 case 0x59:
8191                 case 0x5A:
8192                 case 0x5B:
8193                 case 0x5D:
8194                 case 0x5E:
8195                 case 0x5F:
8196                 case 0x60:
8197                 case 0x61:
8198                 case 0x62:
8199                 case 0x63:
8200                 case 0x64:
8201                 case 0x65:
8202                 case 0x66:
8203                 case 0x67:
8204                 case 0x68:
8205                 case 0x69:
8206                 case 0x6A:
8207                 case 0x6B:
8208                 case 0x6C:
8209                 case 0x6D:
8210                 case 0x6E:
8211                 case 0x6F:
8212                 case 0x70:
8213                 case 0x71:
8214                 case 0x72:
8215                 case 0x73:
8216                 case 0x74:
8217                 case 0x75:
8218                 case 0x76:
8219                 case 0x77:
8220                 case 0x78:
8221                 case 0x79:
8222                 case 0x7A:
8223                 case 0x7B:
8224                 case 0x7C:
8225                 case 0x7D:
8226                 case 0x7E:
8227                 case 0x7F:
8228                 {
8229                     add(current);
8230                     break;
8231                 }
8232 
8233                 // U+0080..U+07FF: bytes C2..DF 80..BF
8234                 case 0xC2:
8235                 case 0xC3:
8236                 case 0xC4:
8237                 case 0xC5:
8238                 case 0xC6:
8239                 case 0xC7:
8240                 case 0xC8:
8241                 case 0xC9:
8242                 case 0xCA:
8243                 case 0xCB:
8244                 case 0xCC:
8245                 case 0xCD:
8246                 case 0xCE:
8247                 case 0xCF:
8248                 case 0xD0:
8249                 case 0xD1:
8250                 case 0xD2:
8251                 case 0xD3:
8252                 case 0xD4:
8253                 case 0xD5:
8254                 case 0xD6:
8255                 case 0xD7:
8256                 case 0xD8:
8257                 case 0xD9:
8258                 case 0xDA:
8259                 case 0xDB:
8260                 case 0xDC:
8261                 case 0xDD:
8262                 case 0xDE:
8263                 case 0xDF:
8264                 {
8265                     if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8266                     {
8267                         return token_type::parse_error;
8268                     }
8269                     break;
8270                 }
8271 
8272                 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8273                 case 0xE0:
8274                 {
8275                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8276                     {
8277                         return token_type::parse_error;
8278                     }
8279                     break;
8280                 }
8281 
8282                 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8283                 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8284                 case 0xE1:
8285                 case 0xE2:
8286                 case 0xE3:
8287                 case 0xE4:
8288                 case 0xE5:
8289                 case 0xE6:
8290                 case 0xE7:
8291                 case 0xE8:
8292                 case 0xE9:
8293                 case 0xEA:
8294                 case 0xEB:
8295                 case 0xEC:
8296                 case 0xEE:
8297                 case 0xEF:
8298                 {
8299                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8300                     {
8301                         return token_type::parse_error;
8302                     }
8303                     break;
8304                 }
8305 
8306                 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8307                 case 0xED:
8308                 {
8309                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8310                     {
8311                         return token_type::parse_error;
8312                     }
8313                     break;
8314                 }
8315 
8316                 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8317                 case 0xF0:
8318                 {
8319                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8320                     {
8321                         return token_type::parse_error;
8322                     }
8323                     break;
8324                 }
8325 
8326                 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8327                 case 0xF1:
8328                 case 0xF2:
8329                 case 0xF3:
8330                 {
8331                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8332                     {
8333                         return token_type::parse_error;
8334                     }
8335                     break;
8336                 }
8337 
8338                 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8339                 case 0xF4:
8340                 {
8341                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8342                     {
8343                         return token_type::parse_error;
8344                     }
8345                     break;
8346                 }
8347 
8348                 // remaining bytes (80..C1 and F5..FF) are ill-formed
8349                 default:
8350                 {
8351                     error_message = "invalid string: ill-formed UTF-8 byte";
8352                     return token_type::parse_error;
8353                 }
8354             }
8355         }
8356     }
8357 
8358     /*! 
8359      * @brief scan a comment 
8360      * @return whether comment could be scanned successfully 
8361      */
8362     bool scan_comment()
8363     {
8364         switch (get())
8365         {
8366             // single-line comments skip input until a newline or EOF is read
8367             case '/':
8368             {
8369                 while (true)
8370                 {
8371                     switch (get())
8372                     {
8373                         case '\n':
8374                         case '\r':
8375                         case char_traits<char_type>::eof():
8376                         case '\0':
8377                             return true;
8378 
8379                         default:
8380                             break;
8381                     }
8382                 }
8383             }
8384 
8385             // multi-line comments skip input until */ is read
8386             case '*':
8387             {
8388                 while (true)
8389                 {
8390                     switch (get())
8391                     {
8392                         case char_traits<char_type>::eof():
8393                         case '\0':
8394                         {
8395                             error_message = "invalid comment; missing closing '*/'";
8396                             return false;
8397                         }
8398 
8399                         case '*':
8400                         {
8401                             switch (get())
8402                             {
8403                                 case '/':
8404                                     return true;
8405 
8406                                 default:
8407                                 {
8408                                     unget();
8409                                     continue;
8410                                 }
8411                             }
8412                         }
8413 
8414                         default:
8415                             continue;
8416                     }
8417                 }
8418             }
8419 
8420             // unexpected character after reading '/'
8421             default:
8422             {
8423                 error_message = "invalid comment; expecting '/' or '*' after '/'";
8424                 return false;
8425             }
8426         }
8427     }
8428 
8429     JSON_HEDLEY_NON_NULL(2)
8430     static void strtof(float& f, const char* str, char** endptr) noexcept
8431     {
8432         f = std::strtof(str, endptr);
8433     }
8434 
8435     JSON_HEDLEY_NON_NULL(2)
8436     static void strtof(double& f, const char* str, char** endptr) noexcept
8437     {
8438         f = std::strtod(str, endptr);
8439     }
8440 
8441     JSON_HEDLEY_NON_NULL(2)
8442     static void strtof(long double& f, const char* str, char** endptr) noexcept
8443     {
8444         f = std::strtold(str, endptr);
8445     }
8446 
8447     /*! 
8448     @brief scan a number literal 
8449  
8450     This function scans a string according to Sect. 6 of RFC 8259. 
8451  
8452     The function is realized with a deterministic finite state machine derived 
8453     from the grammar described in RFC 8259. Starting in state "init", the 
8454     input is read and used to determined the next state. Only state "done" 
8455     accepts the number. State "error" is a trap state to model errors. In the 
8456     table below, "anything" means any character but the ones listed before. 
8457  
8458     state    | 0        | 1-9      | e E      | +       | -       | .        | anything 
8459     ---------|----------|----------|----------|---------|---------|----------|----------- 
8460     init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error] 
8461     minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error] 
8462     zero     | done     | done     | exponent | done    | done    | decimal1 | done 
8463     any1     | any1     | any1     | exponent | done    | done    | decimal1 | done 
8464     decimal1 | decimal2 | decimal2 | [error]  | [error] | [error] | [error]  | [error] 
8465     decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done 
8466     exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error] 
8467     sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error] 
8468     any2     | any2     | any2     | done     | done    | done    | done     | done 
8469  
8470     The state machine is realized with one label per state (prefixed with 
8471     "scan_number_") and `goto` statements between them. The state machine 
8472     contains cycles, but any cycle can be left when EOF is read. Therefore, 
8473     the function is guaranteed to terminate. 
8474  
8475     During scanning, the read bytes are stored in token_buffer. This string is 
8476     then converted to a signed integer, an unsigned integer, or a 
8477     floating-point number. 
8478  
8479     @return token_type::value_unsigned, token_type::value_integer, or 
8480             token_type::value_float if number could be successfully scanned, 
8481             token_type::parse_error otherwise 
8482  
8483     @note The scanner is independent of the current locale. Internally, the 
8484           locale's decimal point is used instead of `.` to work with the 
8485           locale-dependent converters. 
8486     */
8487     token_type scan_number()  // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
8488     {
8489         // reset token_buffer to store the number's bytes
8490         reset();
8491 
8492         // the type of the parsed number; initially set to unsigned; will be
8493         // changed if minus sign, decimal point or exponent is read
8494         token_type number_type = token_type::value_unsigned;
8495 
8496         // state (init): we just found out we need to scan a number
8497         switch (current)
8498         {
8499             case '-':
8500             {
8501                 add(current);
8502                 goto scan_number_minus;
8503             }
8504 
8505             case '0':
8506             {
8507                 add(current);
8508                 goto scan_number_zero;
8509             }
8510 
8511             case '1':
8512             case '2':
8513             case '3':
8514             case '4':
8515             case '5':
8516             case '6':
8517             case '7':
8518             case '8':
8519             case '9':
8520             {
8521                 add(current);
8522                 goto scan_number_any1;
8523             }
8524 
8525             // all other characters are rejected outside scan_number()
8526             default:            // LCOV_EXCL_LINE
8527                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8528         }
8529 
8530 scan_number_minus:
8531         // state: we just parsed a leading minus sign
8532         number_type = token_type::value_integer;
8533         switch (get())
8534         {
8535             case '0':
8536             {
8537                 add(current);
8538                 goto scan_number_zero;
8539             }
8540 
8541             case '1':
8542             case '2':
8543             case '3':
8544             case '4':
8545             case '5':
8546             case '6':
8547             case '7':
8548             case '8':
8549             case '9':
8550             {
8551                 add(current);
8552                 goto scan_number_any1;
8553             }
8554 
8555             default:
8556             {
8557                 error_message = "invalid number; expected digit after '-'";
8558                 return token_type::parse_error;
8559             }
8560         }
8561 
8562 scan_number_zero:
8563         // state: we just parse a zero (maybe with a leading minus sign)
8564         switch (get())
8565         {
8566             case '.':
8567             {
8568                 add(decimal_point_char);
8569                 decimal_point_position = token_buffer.size() - 1;
8570                 goto scan_number_decimal1;
8571             }
8572 
8573             case 'e':
8574             case 'E':
8575             {
8576                 add(current);
8577                 goto scan_number_exponent;
8578             }
8579 
8580             default:
8581                 goto scan_number_done;
8582         }
8583 
8584 scan_number_any1:
8585         // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8586         switch (get())
8587         {
8588             case '0':
8589             case '1':
8590             case '2':
8591             case '3':
8592             case '4':
8593             case '5':
8594             case '6':
8595             case '7':
8596             case '8':
8597             case '9':
8598             {
8599                 add(current);
8600                 goto scan_number_any1;
8601             }
8602 
8603             case '.':
8604             {
8605                 add(decimal_point_char);
8606                 decimal_point_position = token_buffer.size() - 1;
8607                 goto scan_number_decimal1;
8608             }
8609 
8610             case 'e':
8611             case 'E':
8612             {
8613                 add(current);
8614                 goto scan_number_exponent;
8615             }
8616 
8617             default:
8618                 goto scan_number_done;
8619         }
8620 
8621 scan_number_decimal1:
8622         // state: we just parsed a decimal point
8623         number_type = token_type::value_float;
8624         switch (get())
8625         {
8626             case '0':
8627             case '1':
8628             case '2':
8629             case '3':
8630             case '4':
8631             case '5':
8632             case '6':
8633             case '7':
8634             case '8':
8635             case '9':
8636             {
8637                 add(current);
8638                 goto scan_number_decimal2;
8639             }
8640 
8641             default:
8642             {
8643                 error_message = "invalid number; expected digit after '.'";
8644                 return token_type::parse_error;
8645             }
8646         }
8647 
8648 scan_number_decimal2:
8649         // we just parsed at least one number after a decimal point
8650         switch (get())
8651         {
8652             case '0':
8653             case '1':
8654             case '2':
8655             case '3':
8656             case '4':
8657             case '5':
8658             case '6':
8659             case '7':
8660             case '8':
8661             case '9':
8662             {
8663                 add(current);
8664                 goto scan_number_decimal2;
8665             }
8666 
8667             case 'e':
8668             case 'E':
8669             {
8670                 add(current);
8671                 goto scan_number_exponent;
8672             }
8673 
8674             default:
8675                 goto scan_number_done;
8676         }
8677 
8678 scan_number_exponent:
8679         // we just parsed an exponent
8680         number_type = token_type::value_float;
8681         switch (get())
8682         {
8683             case '+':
8684             case '-':
8685             {
8686                 add(current);
8687                 goto scan_number_sign;
8688             }
8689 
8690             case '0':
8691             case '1':
8692             case '2':
8693             case '3':
8694             case '4':
8695             case '5':
8696             case '6':
8697             case '7':
8698             case '8':
8699             case '9':
8700             {
8701                 add(current);
8702                 goto scan_number_any2;
8703             }
8704 
8705             default:
8706             {
8707                 error_message =
8708                     "invalid number; expected '+', '-', or digit after exponent";
8709                 return token_type::parse_error;
8710             }
8711         }
8712 
8713 scan_number_sign:
8714         // we just parsed an exponent sign
8715         switch (get())
8716         {
8717             case '0':
8718             case '1':
8719             case '2':
8720             case '3':
8721             case '4':
8722             case '5':
8723             case '6':
8724             case '7':
8725             case '8':
8726             case '9':
8727             {
8728                 add(current);
8729                 goto scan_number_any2;
8730             }
8731 
8732             default:
8733             {
8734                 error_message = "invalid number; expected digit after exponent sign";
8735                 return token_type::parse_error;
8736             }
8737         }
8738 
8739 scan_number_any2:
8740         // we just parsed a number after the exponent or exponent sign
8741         switch (get())
8742         {
8743             case '0':
8744             case '1':
8745             case '2':
8746             case '3':
8747             case '4':
8748             case '5':
8749             case '6':
8750             case '7':
8751             case '8':
8752             case '9':
8753             {
8754                 add(current);
8755                 goto scan_number_any2;
8756             }
8757 
8758             default:
8759                 goto scan_number_done;
8760         }
8761 
8762 scan_number_done:
8763         // unget the character after the number (we only read it to know that
8764         // we are done scanning a number)
8765         unget();
8766 
8767         char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8768         errno = 0;
8769 
8770         // try to parse integers first and fall back to floats
8771         if (number_type == token_type::value_unsigned)
8772         {
8773             const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8774 
8775             // we checked the number format before
8776             JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8777 
8778             if (errno != ERANGE)
8779             {
8780                 value_unsigned = static_cast<number_unsigned_t>(x);
8781                 if (value_unsigned == x)
8782                 {
8783                     return token_type::value_unsigned;
8784                 }
8785             }
8786         }
8787         else if (number_type == token_type::value_integer)
8788         {
8789             const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8790 
8791             // we checked the number format before
8792             JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8793 
8794             if (errno != ERANGE)
8795             {
8796                 value_integer = static_cast<number_integer_t>(x);
8797                 if (value_integer == x)
8798                 {
8799                     return token_type::value_integer;
8800                 }
8801             }
8802         }
8803 
8804         // this code is reached if we parse a floating-point number or if an
8805         // integer conversion above failed
8806         strtof(value_float, token_buffer.data(), &endptr);
8807 
8808         // we checked the number format before
8809         JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8810 
8811         return token_type::value_float;
8812     }
8813 
8814     /*! 
8815     @param[in] literal_text  the literal text to expect 
8816     @param[in] length        the length of the passed literal text 
8817     @param[in] return_type   the token type to return on success 
8818     */
8819     JSON_HEDLEY_NON_NULL(2)
8820     token_type scan_literal(const char_type* literal_text, const std::size_t length,
8821                             token_type return_type)
8822     {
8823         JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8824         for (std::size_t i = 1; i < length; ++i)
8825         {
8826             if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8827             {
8828                 error_message = "invalid literal";
8829                 return token_type::parse_error;
8830             }
8831         }
8832         return return_type;
8833     }
8834 
8835     /////////////////////
8836     // input management
8837     /////////////////////
8838 
8839     /// reset token_buffer; current character is beginning of token
8840     void reset() noexcept
8841     {
8842         token_buffer.clear();
8843         token_string.clear();
8844         decimal_point_position = std::string::npos;
8845         token_string.push_back(char_traits<char_type>::to_char_type(current));
8846     }
8847 
8848     /* 
8849     @brief get next character from the input 
8850  
8851     This function provides the interface to the used input adapter. It does 
8852     not throw in case the input reached EOF, but returns a 
8853     `char_traits<char>::eof()` in that case.  Stores the scanned characters 
8854     for use in error messages. 
8855  
8856     @return character read from the input 
8857     */
8858     char_int_type get()
8859     {
8860         ++position.chars_read_total;
8861         ++position.chars_read_current_line;
8862 
8863         if (next_unget)
8864         {
8865             // just reset the next_unget variable and work with current
8866             next_unget = false;
8867         }
8868         else
8869         {
8870             current = ia.get_character();
8871         }
8872 
8873         if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8874         {
8875             token_string.push_back(char_traits<char_type>::to_char_type(current));
8876         }
8877 
8878         if (current == '\n')
8879         {
8880             ++position.lines_read;
8881             position.chars_read_current_line = 0;
8882         }
8883 
8884         return current;
8885     }
8886 
8887     /*! 
8888     @brief unget current character (read it again on next get) 
8889  
8890     We implement unget by setting variable next_unget to true. The input is not 
8891     changed - we just simulate ungetting by modifying chars_read_total, 
8892     chars_read_current_line, and token_string. The next call to get() will 
8893     behave as if the unget character is read again. 
8894     */
8895     void unget()
8896     {
8897         next_unget = true;
8898 
8899         --position.chars_read_total;
8900 
8901         // in case we "unget" a newline, we have to also decrement the lines_read
8902         if (position.chars_read_current_line == 0)
8903         {
8904             if (position.lines_read > 0)
8905             {
8906                 --position.lines_read;
8907             }
8908         }
8909         else
8910         {
8911             --position.chars_read_current_line;
8912         }
8913 
8914         if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8915         {
8916             JSON_ASSERT(!token_string.empty());
8917             token_string.pop_back();
8918         }
8919     }
8920 
8921     /// add a character to token_buffer
8922     void add(char_int_type c)
8923     {
8924         token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8925     }
8926 
8927   public:
8928     /////////////////////
8929     // value getters
8930     /////////////////////
8931 
8932     /// return integer value
8933     constexpr number_integer_t get_number_integer() const noexcept
8934     {
8935         return value_integer;
8936     }
8937 
8938     /// return unsigned integer value
8939     constexpr number_unsigned_t get_number_unsigned() const noexcept
8940     {
8941         return value_unsigned;
8942     }
8943 
8944     /// return floating-point value
8945     constexpr number_float_t get_number_float() const noexcept
8946     {
8947         return value_float;
8948     }
8949 
8950     /// return current string value (implicitly resets the token; useful only once)
8951     string_t& get_string()
8952     {
8953         // translate decimal points from locale back to '.' (#4084)
8954         if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8955         {
8956             token_buffer[decimal_point_position] = '.';
8957         }
8958         return token_buffer;
8959     }
8960 
8961     /////////////////////
8962     // diagnostics
8963     /////////////////////
8964 
8965     /// return position of last read token
8966     constexpr position_t get_position() const noexcept
8967     {
8968         return position;
8969     }
8970 
8971     /// return the last read token (for errors only).  Will never contain EOF
8972     /// (an arbitrary value that is not a valid char value, often -1), because
8973     /// 255 may legitimately occur.  May contain NUL, which should be escaped.
8974     std::string get_token_string() const
8975     {
8976         // escape control characters
8977         std::string result;
8978         for (const auto c : token_string)
8979         {
8980             if (static_cast<unsigned char>(c) <= '\x1F')
8981             {
8982                 // escape control characters
8983                 std::array<char, 9> cs{{}};
8984                 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8985                 result += cs.data();
8986             }
8987             else
8988             {
8989                 // add character as is
8990                 result.push_back(static_cast<std::string::value_type>(c));
8991             }
8992         }
8993 
8994         return result;
8995     }
8996 
8997     /// return syntax error message
8998     JSON_HEDLEY_RETURNS_NON_NULL
8999     constexpr const char* get_error_message() const noexcept
9000     {
9001         return error_message;
9002     }
9003 
9004     /////////////////////
9005     // actual scanner
9006     /////////////////////
9007 
9008     /*! 
9009     @brief skip the UTF-8 byte order mark 
9010     @return true iff there is no BOM or the correct BOM has been skipped 
9011     */
9012     bool skip_bom()
9013     {
9014         if (get() == 0xEF)
9015         {
9016             // check if we completely parse the BOM
9017             return get() == 0xBB && get() == 0xBF;
9018         }
9019 
9020         // the first character is not the beginning of the BOM; unget it to
9021         // process is later
9022         unget();
9023         return true;
9024     }
9025 
9026     void skip_whitespace()
9027     {
9028         do
9029         {
9030             get();
9031         }
9032         while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
9033     }
9034 
9035     token_type scan()
9036     {
9037         // initially, skip the BOM
9038         if (position.chars_read_total == 0 && !skip_bom())
9039         {
9040             error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
9041             return token_type::parse_error;
9042         }
9043 
9044         // read next character and ignore whitespace
9045         skip_whitespace();
9046 
9047         // ignore comments
9048         while (ignore_comments && current == '/')
9049         {
9050             if (!scan_comment())
9051             {
9052                 return token_type::parse_error;
9053             }
9054 
9055             // skip following whitespace
9056             skip_whitespace();
9057         }
9058 
9059         switch (current)
9060         {
9061             // structural characters
9062             case '[':
9063                 return token_type::begin_array;
9064             case ']':
9065                 return token_type::end_array;
9066             case '{':
9067                 return token_type::begin_object;
9068             case '}':
9069                 return token_type::end_object;
9070             case ':':
9071                 return token_type::name_separator;
9072             case ',':
9073                 return token_type::value_separator;
9074 
9075             // literals
9076             case 't':
9077             {
9078                 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
9079                 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
9080             }
9081             case 'f':
9082             {
9083                 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
9084                 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
9085             }
9086             case 'n':
9087             {
9088                 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
9089                 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
9090             }
9091 
9092             // string
9093             case '\"':
9094                 return scan_string();
9095 
9096             // number
9097             case '-':
9098             case '0':
9099             case '1':
9100             case '2':
9101             case '3':
9102             case '4':
9103             case '5':
9104             case '6':
9105             case '7':
9106             case '8':
9107             case '9':
9108                 return scan_number();
9109 
9110             // end of input (the null byte is needed when parsing from
9111             // string literals)
9112             case '\0':
9113             case char_traits<char_type>::eof():
9114                 return token_type::end_of_input;
9115 
9116             // error
9117             default:
9118                 error_message = "invalid literal";
9119                 return token_type::parse_error;
9120         }
9121     }
9122 
9123   private:
9124     /// input adapter
9125     InputAdapterType ia;
9126 
9127     /// whether comments should be ignored (true) or signaled as errors (false)
9128     const bool ignore_comments = false;
9129 
9130     /// the current character
9131     char_int_type current = char_traits<char_type>::eof();
9132 
9133     /// whether the next get() call should just return current
9134     bool next_unget = false;
9135 
9136     /// the start position of the current token
9137     position_t position {};
9138 
9139     /// raw input token string (for error messages)
9140     std::vector<char_type> token_string {};
9141 
9142     /// buffer for variable-length tokens (numbers, strings)
9143     string_t token_buffer {};
9144 
9145     /// a description of occurred lexer errors
9146     const char* error_message = "";
9147 
9148     // number values
9149     number_integer_t value_integer = 0;
9150     number_unsigned_t value_unsigned = 0;
9151     number_float_t value_float = 0;
9152 
9153     /// the decimal point
9154     const char_int_type decimal_point_char = '.';
9155     /// the position of the decimal point in the input
9156     std::size_t decimal_point_position = std::string::npos;
9157 };
9158 
9159 }  // namespace detail
9160 NLOHMANN_JSON_NAMESPACE_END
9161 
9162 // #include <nlohmann/detail/macro_scope.hpp>
9163 
9164 // #include <nlohmann/detail/meta/is_sax.hpp>
9165 //     __ _____ _____ _____
9166 //  __|  |   __|     |   | |  JSON for Modern C++
9167 // |  |  |__   |  |  | | | |  version 3.11.3
9168 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
9169 //
9170 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
9171 // SPDX-License-Identifier: MIT
9172 
9173 
9174 
9175 #include <cstdint> // size_t
9176 #include <utility> // declval
9177 #include <string> // string
9178 
9179 // #include <nlohmann/detail/abi_macros.hpp>
9180 
9181 // #include <nlohmann/detail/meta/detected.hpp>
9182 
9183 // #include <nlohmann/detail/meta/type_traits.hpp>
9184 
9185 
9186 NLOHMANN_JSON_NAMESPACE_BEGIN
9187 namespace detail
9188 {
9189 
9190 template<typename T>
9191 using null_function_t = decltype(std::declval<T&>().null());
9192 
9193 template<typename T>
9194 using boolean_function_t =
9195     decltype(std::declval<T&>().boolean(std::declval<bool>()));
9196 
9197 template<typename T, typename Integer>
9198 using number_integer_function_t =
9199     decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9200 
9201 template<typename T, typename Unsigned>
9202 using number_unsigned_function_t =
9203     decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9204 
9205 template<typename T, typename Float, typename String>
9206 using number_float_function_t = decltype(std::declval<T&>().number_float(
9207                                     std::declval<Float>(), std::declval<const String&>()));
9208 
9209 template<typename T, typename String>
9210 using string_function_t =
9211     decltype(std::declval<T&>().string(std::declval<String&>()));
9212 
9213 template<typename T, typename Binary>
9214 using binary_function_t =
9215     decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9216 
9217 template<typename T>
9218 using start_object_function_t =
9219     decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9220 
9221 template<typename T, typename String>
9222 using key_function_t =
9223     decltype(std::declval<T&>().key(std::declval<String&>()));
9224 
9225 template<typename T>
9226 using end_object_function_t = decltype(std::declval<T&>().end_object());
9227 
9228 template<typename T>
9229 using start_array_function_t =
9230     decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9231 
9232 template<typename T>
9233 using end_array_function_t = decltype(std::declval<T&>().end_array());
9234 
9235 template<typename T, typename Exception>
9236 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9237         std::declval<std::size_t>(), std::declval<const std::string&>(),
9238         std::declval<const Exception&>()));
9239 
9240 template<typename SAX, typename BasicJsonType>
9241 struct is_sax
9242 {
9243   private:
9244     static_assert(is_basic_json<BasicJsonType>::value,
9245                   "BasicJsonType must be of type basic_json<...>");
9246 
9247     using number_integer_t = typename BasicJsonType::number_integer_t;
9248     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9249     using number_float_t = typename BasicJsonType::number_float_t;
9250     using string_t = typename BasicJsonType::string_t;
9251     using binary_t = typename BasicJsonType::binary_t;
9252     using exception_t = typename BasicJsonType::exception;
9253 
9254   public:
9255     static constexpr bool value =
9256         is_detected_exact<bool, null_function_t, SAX>::value &&
9257         is_detected_exact<bool, boolean_function_t, SAX>::value &&
9258         is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9259         is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9260         is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9261         is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9262         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9263         is_detected_exact<bool, start_object_function_t, SAX>::value &&
9264         is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9265         is_detected_exact<bool, end_object_function_t, SAX>::value &&
9266         is_detected_exact<bool, start_array_function_t, SAX>::value &&
9267         is_detected_exact<bool, end_array_function_t, SAX>::value &&
9268         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9269 };
9270 
9271 template<typename SAX, typename BasicJsonType>
9272 struct is_sax_static_asserts
9273 {
9274   private:
9275     static_assert(is_basic_json<BasicJsonType>::value,
9276                   "BasicJsonType must be of type basic_json<...>");
9277 
9278     using number_integer_t = typename BasicJsonType::number_integer_t;
9279     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9280     using number_float_t = typename BasicJsonType::number_float_t;
9281     using string_t = typename BasicJsonType::string_t;
9282     using binary_t = typename BasicJsonType::binary_t;
9283     using exception_t = typename BasicJsonType::exception;
9284 
9285   public:
9286     static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9287                   "Missing/invalid function: bool null()");
9288     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9289                   "Missing/invalid function: bool boolean(bool)");
9290     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9291                   "Missing/invalid function: bool boolean(bool)");
9292     static_assert(
9293         is_detected_exact<bool, number_integer_function_t, SAX,
9294         number_integer_t>::value,
9295         "Missing/invalid function: bool number_integer(number_integer_t)");
9296     static_assert(
9297         is_detected_exact<bool, number_unsigned_function_t, SAX,
9298         number_unsigned_t>::value,
9299         "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9300     static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9301                   number_float_t, string_t>::value,
9302                   "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9303     static_assert(
9304         is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9305         "Missing/invalid function: bool string(string_t&)");
9306     static_assert(
9307         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9308         "Missing/invalid function: bool binary(binary_t&)");
9309     static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9310                   "Missing/invalid function: bool start_object(std::size_t)");
9311     static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9312                   "Missing/invalid function: bool key(string_t&)");
9313     static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9314                   "Missing/invalid function: bool end_object()");
9315     static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9316                   "Missing/invalid function: bool start_array(std::size_t)");
9317     static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9318                   "Missing/invalid function: bool end_array()");
9319     static_assert(
9320         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9321         "Missing/invalid function: bool parse_error(std::size_t, const "
9322         "std::string&, const exception&)");
9323 };
9324 
9325 }  // namespace detail
9326 NLOHMANN_JSON_NAMESPACE_END
9327 
9328 // #include <nlohmann/detail/meta/type_traits.hpp>
9329 
9330 // #include <nlohmann/detail/string_concat.hpp>
9331 
9332 // #include <nlohmann/detail/value_t.hpp>
9333 
9334 
9335 NLOHMANN_JSON_NAMESPACE_BEGIN
9336 namespace detail
9337 {
9338 
9339 /// how to treat CBOR tags
9340 enum class cbor_tag_handler_t
9341 {
9342     error,   ///< throw a parse_error exception in case of a tag
9343     ignore,  ///< ignore tags
9344     store    ///< store tags as binary type
9345 };
9346 
9347 /*! 
9348 @brief determine system byte order 
9349  
9350 @return true if and only if system's byte order is little endian 
9351  
9352 @note from https://stackoverflow.com/a/1001328/266378 
9353 */
9354 static inline bool little_endianness(int num = 1) noexcept
9355 {
9356     return *reinterpret_cast<char*>(&num) == 1;
9357 }
9358 
9359 ///////////////////
9360 // binary reader //
9361 ///////////////////
9362 
9363 /*! 
9364 @brief deserialization of CBOR, MessagePack, and UBJSON values 
9365 */
9366 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9367 class binary_reader
9368 {
9369     using number_integer_t = typename BasicJsonType::number_integer_t;
9370     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9371     using number_float_t = typename BasicJsonType::number_float_t;
9372     using string_t = typename BasicJsonType::string_t;
9373     using binary_t = typename BasicJsonType::binary_t;
9374     using json_sax_t = SAX;
9375     using char_type = typename InputAdapterType::char_type;
9376     using char_int_type = typename char_traits<char_type>::int_type;
9377 
9378   public:
9379     /*! 
9380     @brief create a binary reader 
9381  
9382     @param[in] adapter  input adapter to read from 
9383     */
9384     explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9385     {
9386         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
9387     }
9388 
9389     // make class move-only
9390     binary_reader(const binary_reader&) = delete;
9391     binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9392     binary_reader& operator=(const binary_reader&) = delete;
9393     binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9394     ~binary_reader() = default;
9395 
9396     /*! 
9397     @param[in] format  the binary format to parse 
9398     @param[in] sax_    a SAX event processor 
9399     @param[in] strict  whether to expect the input to be consumed completed 
9400     @param[in] tag_handler  how to treat CBOR tags 
9401  
9402     @return whether parsing was successful 
9403     */
9404     JSON_HEDLEY_NON_NULL(3)
9405     bool sax_parse(const input_format_t format,
9406                    json_sax_t* sax_,
9407                    const bool strict = true,
9408                    const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9409     {
9410         sax = sax_;
9411         bool result = false;
9412 
9413         switch (format)
9414         {
9415             case input_format_t::bson:
9416                 result = parse_bson_internal();
9417                 break;
9418 
9419             case input_format_t::cbor:
9420                 result = parse_cbor_internal(true, tag_handler);
9421                 break;
9422 
9423             case input_format_t::msgpack:
9424                 result = parse_msgpack_internal();
9425                 break;
9426 
9427             case input_format_t::ubjson:
9428             case input_format_t::bjdata:
9429                 result = parse_ubjson_internal();
9430                 break;
9431 
9432             case input_format_t::json: // LCOV_EXCL_LINE
9433             default:            // LCOV_EXCL_LINE
9434                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9435         }
9436 
9437         // strict mode: next byte must be EOF
9438         if (result && strict)
9439         {
9440             if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9441             {
9442                 get_ignore_noop();
9443             }
9444             else
9445             {
9446                 get();
9447             }
9448 
9449             if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
9450             {
9451                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9452                                         exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9453             }
9454         }
9455 
9456         return result;
9457     }
9458 
9459   private:
9460     //////////
9461     // BSON //
9462     //////////
9463 
9464     /*! 
9465     @brief Reads in a BSON-object and passes it to the SAX-parser. 
9466     @return whether a valid BSON-value was passed to the SAX parser 
9467     */
9468     bool parse_bson_internal()
9469     {
9470         std::int32_t document_size{};
9471         get_number<std::int32_t, true>(input_format_t::bson, document_size);
9472 
9473         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9474         {
9475             return false;
9476         }
9477 
9478         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9479         {
9480             return false;
9481         }
9482 
9483         return sax->end_object();
9484     }
9485 
9486     /*! 
9487     @brief Parses a C-style string from the BSON input. 
9488     @param[in,out] result  A reference to the string variable where the read 
9489                             string is to be stored. 
9490     @return `true` if the \x00-byte indicating the end of the string was 
9491              encountered before the EOF; false` indicates an unexpected EOF. 
9492     */
9493     bool get_bson_cstr(string_t& result)
9494     {
9495         auto out = std::back_inserter(result);
9496         while (true)
9497         {
9498             get();
9499             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9500             {
9501                 return false;
9502             }
9503             if (current == 0x00)
9504             {
9505                 return true;
9506             }
9507             *out++ = static_cast<typename string_t::value_type>(current);
9508         }
9509     }
9510 
9511     /*! 
9512     @brief Parses a zero-terminated string of length @a len from the BSON 
9513            input. 
9514     @param[in] len  The length (including the zero-byte at the end) of the 
9515                     string to be read. 
9516     @param[in,out] result  A reference to the string variable where the read 
9517                             string is to be stored. 
9518     @tparam NumberType The type of the length @a len 
9519     @pre len >= 1 
9520     @return `true` if the string was successfully parsed 
9521     */
9522     template<typename NumberType>
9523     bool get_bson_string(const NumberType len, string_t& result)
9524     {
9525         if (JSON_HEDLEY_UNLIKELY(len < 1))
9526         {
9527             auto last_token = get_token_string();
9528             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9529                                     exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9530         }
9531 
9532         return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9533     }
9534 
9535     /*! 
9536     @brief Parses a byte array input of length @a len from the BSON input. 
9537     @param[in] len  The length of the byte array to be read. 
9538     @param[in,out] result  A reference to the binary variable where the read 
9539                             array is to be stored. 
9540     @tparam NumberType The type of the length @a len 
9541     @pre len >= 0 
9542     @return `true` if the byte array was successfully parsed 
9543     */
9544     template<typename NumberType>
9545     bool get_bson_binary(const NumberType len, binary_t& result)
9546     {
9547         if (JSON_HEDLEY_UNLIKELY(len < 0))
9548         {
9549             auto last_token = get_token_string();
9550             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9551                                     exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9552         }
9553 
9554         // All BSON binary values have a subtype
9555         std::uint8_t subtype{};
9556         get_number<std::uint8_t>(input_format_t::bson, subtype);
9557         result.set_subtype(subtype);
9558 
9559         return get_binary(input_format_t::bson, len, result);
9560     }
9561 
9562     /*! 
9563     @brief Read a BSON document element of the given @a element_type. 
9564     @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html 
9565     @param[in] element_type_parse_position The position in the input stream, 
9566                where the `element_type` was read. 
9567     @warning Not all BSON element types are supported yet. An unsupported 
9568              @a element_type will give rise to a parse_error.114: 
9569              Unsupported BSON record type 0x... 
9570     @return whether a valid BSON-object/array was passed to the SAX parser 
9571     */
9572     bool parse_bson_element_internal(const char_int_type element_type,
9573                                      const std::size_t element_type_parse_position)
9574     {
9575         switch (element_type)
9576         {
9577             case 0x01: // double
9578             {
9579                 double number{};
9580                 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9581             }
9582 
9583             case 0x02: // string
9584             {
9585                 std::int32_t len{};
9586                 string_t value;
9587                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9588             }
9589 
9590             case 0x03: // object
9591             {
9592                 return parse_bson_internal();
9593             }
9594 
9595             case 0x04: // array
9596             {
9597                 return parse_bson_array();
9598             }
9599 
9600             case 0x05: // binary
9601             {
9602                 std::int32_t len{};
9603                 binary_t value;
9604                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9605             }
9606 
9607             case 0x08: // boolean
9608             {
9609                 return sax->boolean(get() != 0);
9610             }
9611 
9612             case 0x0A: // null
9613             {
9614                 return sax->null();
9615             }
9616 
9617             case 0x10: // int32
9618             {
9619                 std::int32_t value{};
9620                 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9621             }
9622 
9623             case 0x12: // int64
9624             {
9625                 std::int64_t value{};
9626                 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9627             }
9628 
9629             default: // anything else not supported (yet)
9630             {
9631                 std::array<char, 3> cr{{}};
9632                 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9633                 const std::string cr_str{cr.data()};
9634                 return sax->parse_error(element_type_parse_position, cr_str,
9635                                         parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9636             }
9637         }
9638     }
9639 
9640     /*! 
9641     @brief Read a BSON element list (as specified in the BSON-spec) 
9642  
9643     The same binary layout is used for objects and arrays, hence it must be 
9644     indicated with the argument @a is_array which one is expected 
9645     (true --> array, false --> object). 
9646  
9647     @param[in] is_array Determines if the element list being read is to be 
9648                         treated as an object (@a is_array == false), or as an 
9649                         array (@a is_array == true). 
9650     @return whether a valid BSON-object/array was passed to the SAX parser 
9651     */
9652     bool parse_bson_element_list(const bool is_array)
9653     {
9654         string_t key;
9655 
9656         while (auto element_type = get())
9657         {
9658             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9659             {
9660                 return false;
9661             }
9662 
9663             const std::size_t element_type_parse_position = chars_read;
9664             if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9665             {
9666                 return false;
9667             }
9668 
9669             if (!is_array && !sax->key(key))
9670             {
9671                 return false;
9672             }
9673 
9674             if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9675             {
9676                 return false;
9677             }
9678 
9679             // get_bson_cstr only appends
9680             key.clear();
9681         }
9682 
9683         return true;
9684     }
9685 
9686     /*! 
9687     @brief Reads an array from the BSON input and passes it to the SAX-parser. 
9688     @return whether a valid BSON-array was passed to the SAX parser 
9689     */
9690     bool parse_bson_array()
9691     {
9692         std::int32_t document_size{};
9693         get_number<std::int32_t, true>(input_format_t::bson, document_size);
9694 
9695         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9696         {
9697             return false;
9698         }
9699 
9700         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9701         {
9702             return false;
9703         }
9704 
9705         return sax->end_array();
9706     }
9707 
9708     //////////
9709     // CBOR //
9710     //////////
9711 
9712     /*! 
9713     @param[in] get_char  whether a new character should be retrieved from the 
9714                          input (true) or whether the last read character should 
9715                          be considered instead (false) 
9716     @param[in] tag_handler how CBOR tags should be treated 
9717  
9718     @return whether a valid CBOR value was passed to the SAX parser 
9719     */
9720     bool parse_cbor_internal(const bool get_char,
9721                              const cbor_tag_handler_t tag_handler)
9722     {
9723         switch (get_char ? get() : current)
9724         {
9725             // EOF
9726             case char_traits<char_type>::eof():
9727                 return unexpect_eof(input_format_t::cbor, "value");
9728 
9729             // Integer 0x00..0x17 (0..23)
9730             case 0x00:
9731             case 0x01:
9732             case 0x02:
9733             case 0x03:
9734             case 0x04:
9735             case 0x05:
9736             case 0x06:
9737             case 0x07:
9738             case 0x08:
9739             case 0x09:
9740             case 0x0A:
9741             case 0x0B:
9742             case 0x0C:
9743             case 0x0D:
9744             case 0x0E:
9745             case 0x0F:
9746             case 0x10:
9747             case 0x11:
9748             case 0x12:
9749             case 0x13:
9750             case 0x14:
9751             case 0x15:
9752             case 0x16:
9753             case 0x17:
9754                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9755 
9756             case 0x18: // Unsigned integer (one-byte uint8_t follows)
9757             {
9758                 std::uint8_t number{};
9759                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9760             }
9761 
9762             case 0x19: // Unsigned integer (two-byte uint16_t follows)
9763             {
9764                 std::uint16_t number{};
9765                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9766             }
9767 
9768             case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9769             {
9770                 std::uint32_t number{};
9771                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9772             }
9773 
9774             case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9775             {
9776                 std::uint64_t number{};
9777                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9778             }
9779 
9780             // Negative integer -1-0x00..-1-0x17 (-1..-24)
9781             case 0x20:
9782             case 0x21:
9783             case 0x22:
9784             case 0x23:
9785             case 0x24:
9786             case 0x25:
9787             case 0x26:
9788             case 0x27:
9789             case 0x28:
9790             case 0x29:
9791             case 0x2A:
9792             case 0x2B:
9793             case 0x2C:
9794             case 0x2D:
9795             case 0x2E:
9796             case 0x2F:
9797             case 0x30:
9798             case 0x31:
9799             case 0x32:
9800             case 0x33:
9801             case 0x34:
9802             case 0x35:
9803             case 0x36:
9804             case 0x37:
9805                 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9806 
9807             case 0x38: // Negative integer (one-byte uint8_t follows)
9808             {
9809                 std::uint8_t number{};
9810                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9811             }
9812 
9813             case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9814             {
9815                 std::uint16_t number{};
9816                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9817             }
9818 
9819             case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9820             {
9821                 std::uint32_t number{};
9822                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9823             }
9824 
9825             case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9826             {
9827                 std::uint64_t number{};
9828                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9829                         - static_cast<number_integer_t>(number));
9830             }
9831 
9832             // Binary data (0x00..0x17 bytes follow)
9833             case 0x40:
9834             case 0x41:
9835             case 0x42:
9836             case 0x43:
9837             case 0x44:
9838             case 0x45:
9839             case 0x46:
9840             case 0x47:
9841             case 0x48:
9842             case 0x49:
9843             case 0x4A:
9844             case 0x4B:
9845             case 0x4C:
9846             case 0x4D:
9847             case 0x4E:
9848             case 0x4F:
9849             case 0x50:
9850             case 0x51:
9851             case 0x52:
9852             case 0x53:
9853             case 0x54:
9854             case 0x55:
9855             case 0x56:
9856             case 0x57:
9857             case 0x58: // Binary data (one-byte uint8_t for n follows)
9858             case 0x59: // Binary data (two-byte uint16_t for n follow)
9859             case 0x5A: // Binary data (four-byte uint32_t for n follow)
9860             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9861             case 0x5F: // Binary data (indefinite length)
9862             {
9863                 binary_t b;
9864                 return get_cbor_binary(b) && sax->binary(b);
9865             }
9866 
9867             // UTF-8 string (0x00..0x17 bytes follow)
9868             case 0x60:
9869             case 0x61:
9870             case 0x62:
9871             case 0x63:
9872             case 0x64:
9873             case 0x65:
9874             case 0x66:
9875             case 0x67:
9876             case 0x68:
9877             case 0x69:
9878             case 0x6A:
9879             case 0x6B:
9880             case 0x6C:
9881             case 0x6D:
9882             case 0x6E:
9883             case 0x6F:
9884             case 0x70:
9885             case 0x71:
9886             case 0x72:
9887             case 0x73:
9888             case 0x74:
9889             case 0x75:
9890             case 0x76:
9891             case 0x77:
9892             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9893             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9894             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9895             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9896             case 0x7F: // UTF-8 string (indefinite length)
9897             {
9898                 string_t s;
9899                 return get_cbor_string(s) && sax->string(s);
9900             }
9901 
9902             // array (0x00..0x17 data items follow)
9903             case 0x80:
9904             case 0x81:
9905             case 0x82:
9906             case 0x83:
9907             case 0x84:
9908             case 0x85:
9909             case 0x86:
9910             case 0x87:
9911             case 0x88:
9912             case 0x89:
9913             case 0x8A:
9914             case 0x8B:
9915             case 0x8C:
9916             case 0x8D:
9917             case 0x8E:
9918             case 0x8F:
9919             case 0x90:
9920             case 0x91:
9921             case 0x92:
9922             case 0x93:
9923             case 0x94:
9924             case 0x95:
9925             case 0x96:
9926             case 0x97:
9927                 return get_cbor_array(
9928                            conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9929 
9930             case 0x98: // array (one-byte uint8_t for n follows)
9931             {
9932                 std::uint8_t len{};
9933                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9934             }
9935 
9936             case 0x99: // array (two-byte uint16_t for n follow)
9937             {
9938                 std::uint16_t len{};
9939                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9940             }
9941 
9942             case 0x9A: // array (four-byte uint32_t for n follow)
9943             {
9944                 std::uint32_t len{};
9945                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9946             }
9947 
9948             case 0x9B: // array (eight-byte uint64_t for n follow)
9949             {
9950                 std::uint64_t len{};
9951                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9952             }
9953 
9954             case 0x9F: // array (indefinite length)
9955                 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9956 
9957             // map (0x00..0x17 pairs of data items follow)
9958             case 0xA0:
9959             case 0xA1:
9960             case 0xA2:
9961             case 0xA3:
9962             case 0xA4:
9963             case 0xA5:
9964             case 0xA6:
9965             case 0xA7:
9966             case 0xA8:
9967             case 0xA9:
9968             case 0xAA:
9969             case 0xAB:
9970             case 0xAC:
9971             case 0xAD:
9972             case 0xAE:
9973             case 0xAF:
9974             case 0xB0:
9975             case 0xB1:
9976             case 0xB2:
9977             case 0xB3:
9978             case 0xB4:
9979             case 0xB5:
9980             case 0xB6:
9981             case 0xB7:
9982                 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9983 
9984             case 0xB8: // map (one-byte uint8_t for n follows)
9985             {
9986                 std::uint8_t len{};
9987                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9988             }
9989 
9990             case 0xB9: // map (two-byte uint16_t for n follow)
9991             {
9992                 std::uint16_t len{};
9993                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9994             }
9995 
9996             case 0xBA: // map (four-byte uint32_t for n follow)
9997             {
9998                 std::uint32_t len{};
9999                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10000             }
10001 
10002             case 0xBB: // map (eight-byte uint64_t for n follow)
10003             {
10004                 std::uint64_t len{};
10005                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10006             }
10007 
10008             case 0xBF: // map (indefinite length)
10009                 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
10010 
10011             case 0xC6: // tagged item
10012             case 0xC7:
10013             case 0xC8:
10014             case 0xC9:
10015             case 0xCA:
10016             case 0xCB:
10017             case 0xCC:
10018             case 0xCD:
10019             case 0xCE:
10020             case 0xCF:
10021             case 0xD0:
10022             case 0xD1:
10023             case 0xD2:
10024             case 0xD3:
10025             case 0xD4:
10026             case 0xD8: // tagged item (1 bytes follow)
10027             case 0xD9: // tagged item (2 bytes follow)
10028             case 0xDA: // tagged item (4 bytes follow)
10029             case 0xDB: // tagged item (8 bytes follow)
10030             {
10031                 switch (tag_handler)
10032                 {
10033                     case cbor_tag_handler_t::error:
10034                     {
10035                         auto last_token = get_token_string();
10036                         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10037                                                 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10038                     }
10039 
10040                     case cbor_tag_handler_t::ignore:
10041                     {
10042                         // ignore binary subtype
10043                         switch (current)
10044                         {
10045                             case 0xD8:
10046                             {
10047                                 std::uint8_t subtype_to_ignore{};
10048                                 get_number(input_format_t::cbor, subtype_to_ignore);
10049                                 break;
10050                             }
10051                             case 0xD9:
10052                             {
10053                                 std::uint16_t subtype_to_ignore{};
10054                                 get_number(input_format_t::cbor, subtype_to_ignore);
10055                                 break;
10056                             }
10057                             case 0xDA:
10058                             {
10059                                 std::uint32_t subtype_to_ignore{};
10060                                 get_number(input_format_t::cbor, subtype_to_ignore);
10061                                 break;
10062                             }
10063                             case 0xDB:
10064                             {
10065                                 std::uint64_t subtype_to_ignore{};
10066                                 get_number(input_format_t::cbor, subtype_to_ignore);
10067                                 break;
10068                             }
10069                             default:
10070                                 break;
10071                         }
10072                         return parse_cbor_internal(true, tag_handler);
10073                     }
10074 
10075                     case cbor_tag_handler_t::store:
10076                     {
10077                         binary_t b;
10078                         // use binary subtype and store in binary container
10079                         switch (current)
10080                         {
10081                             case 0xD8:
10082                             {
10083                                 std::uint8_t subtype{};
10084                                 get_number(input_format_t::cbor, subtype);
10085                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10086                                 break;
10087                             }
10088                             case 0xD9:
10089                             {
10090                                 std::uint16_t subtype{};
10091                                 get_number(input_format_t::cbor, subtype);
10092                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10093                                 break;
10094                             }
10095                             case 0xDA:
10096                             {
10097                                 std::uint32_t subtype{};
10098                                 get_number(input_format_t::cbor, subtype);
10099                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10100                                 break;
10101                             }
10102                             case 0xDB:
10103                             {
10104                                 std::uint64_t subtype{};
10105                                 get_number(input_format_t::cbor, subtype);
10106                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10107                                 break;
10108                             }
10109                             default:
10110                                 return parse_cbor_internal(true, tag_handler);
10111                         }
10112                         get();
10113                         return get_cbor_binary(b) && sax->binary(b);
10114                     }
10115 
10116                     default:                 // LCOV_EXCL_LINE
10117                         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10118                         return false;        // LCOV_EXCL_LINE
10119                 }
10120             }
10121 
10122             case 0xF4: // false
10123                 return sax->boolean(false);
10124 
10125             case 0xF5: // true
10126                 return sax->boolean(true);
10127 
10128             case 0xF6: // null
10129                 return sax->null();
10130 
10131             case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10132             {
10133                 const auto byte1_raw = get();
10134                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10135                 {
10136                     return false;
10137                 }
10138                 const auto byte2_raw = get();
10139                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10140                 {
10141                     return false;
10142                 }
10143 
10144                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10145                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10146 
10147                 // code from RFC 7049, Appendix D, Figure 3:
10148                 // As half-precision floating-point numbers were only added
10149                 // to IEEE 754 in 2008, today's programming platforms often
10150                 // still only have limited support for them. It is very
10151                 // easy to include at least decoding support for them even
10152                 // without such support. An example of a small decoder for
10153                 // half-precision floating-point numbers in the C language
10154                 // is shown in Fig. 3.
10155                 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10156                 const double val = [&half]
10157                 {
10158                     const int exp = (half >> 10u) & 0x1Fu;
10159                     const unsigned int mant = half & 0x3FFu;
10160                     JSON_ASSERT(0 <= exp&& exp <= 32);
10161                     JSON_ASSERT(mant <= 1024);
10162                     switch (exp)
10163                     {
10164                         case 0:
10165                             return std::ldexp(mant, -24);
10166                         case 31:
10167                             return (mant == 0)
10168                             ? std::numeric_limits<double>::infinity()
10169                             : std::numeric_limits<double>::quiet_NaN();
10170                         default:
10171                             return std::ldexp(mant + 1024, exp - 25);
10172                     }
10173                 }();
10174                 return sax->number_float((half & 0x8000u) != 0
10175                                          ? static_cast<number_float_t>(-val)
10176                                          : static_cast<number_float_t>(val), "");
10177             }
10178 
10179             case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10180             {
10181                 float number{};
10182                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10183             }
10184 
10185             case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10186             {
10187                 double number{};
10188                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10189             }
10190 
10191             default: // anything else (0xFF is handled inside the other types)
10192             {
10193                 auto last_token = get_token_string();
10194                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10195                                         exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10196             }
10197         }
10198     }
10199 
10200     /*! 
10201     @brief reads a CBOR string 
10202  
10203     This function first reads starting bytes to determine the expected 
10204     string length and then copies this number of bytes into a string. 
10205     Additionally, CBOR's strings with indefinite lengths are supported. 
10206  
10207     @param[out] result  created string 
10208  
10209     @return whether string creation completed 
10210     */
10211     bool get_cbor_string(string_t& result)
10212     {
10213         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10214         {
10215             return false;
10216         }
10217 
10218         switch (current)
10219         {
10220             // UTF-8 string (0x00..0x17 bytes follow)
10221             case 0x60:
10222             case 0x61:
10223             case 0x62:
10224             case 0x63:
10225             case 0x64:
10226             case 0x65:
10227             case 0x66:
10228             case 0x67:
10229             case 0x68:
10230             case 0x69:
10231             case 0x6A:
10232             case 0x6B:
10233             case 0x6C:
10234             case 0x6D:
10235             case 0x6E:
10236             case 0x6F:
10237             case 0x70:
10238             case 0x71:
10239             case 0x72:
10240             case 0x73:
10241             case 0x74:
10242             case 0x75:
10243             case 0x76:
10244             case 0x77:
10245             {
10246                 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10247             }
10248 
10249             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10250             {
10251                 std::uint8_t len{};
10252                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10253             }
10254 
10255             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10256             {
10257                 std::uint16_t len{};
10258                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10259             }
10260 
10261             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10262             {
10263                 std::uint32_t len{};
10264                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10265             }
10266 
10267             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10268             {
10269                 std::uint64_t len{};
10270                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10271             }
10272 
10273             case 0x7F: // UTF-8 string (indefinite length)
10274             {
10275                 while (get() != 0xFF)
10276                 {
10277                     string_t chunk;
10278                     if (!get_cbor_string(chunk))
10279                     {
10280                         return false;
10281                     }
10282                     result.append(chunk);
10283                 }
10284                 return true;
10285             }
10286 
10287             default:
10288             {
10289                 auto last_token = get_token_string();
10290                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10291                                         exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10292             }
10293         }
10294     }
10295 
10296     /*! 
10297     @brief reads a CBOR byte array 
10298  
10299     This function first reads starting bytes to determine the expected 
10300     byte array length and then copies this number of bytes into the byte array. 
10301     Additionally, CBOR's byte arrays with indefinite lengths are supported. 
10302  
10303     @param[out] result  created byte array 
10304  
10305     @return whether byte array creation completed 
10306     */
10307     bool get_cbor_binary(binary_t& result)
10308     {
10309         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10310         {
10311             return false;
10312         }
10313 
10314         switch (current)
10315         {
10316             // Binary data (0x00..0x17 bytes follow)
10317             case 0x40:
10318             case 0x41:
10319             case 0x42:
10320             case 0x43:
10321             case 0x44:
10322             case 0x45:
10323             case 0x46:
10324             case 0x47:
10325             case 0x48:
10326             case 0x49:
10327             case 0x4A:
10328             case 0x4B:
10329             case 0x4C:
10330             case 0x4D:
10331             case 0x4E:
10332             case 0x4F:
10333             case 0x50:
10334             case 0x51:
10335             case 0x52:
10336             case 0x53:
10337             case 0x54:
10338             case 0x55:
10339             case 0x56:
10340             case 0x57:
10341             {
10342                 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10343             }
10344 
10345             case 0x58: // Binary data (one-byte uint8_t for n follows)
10346             {
10347                 std::uint8_t len{};
10348                 return get_number(input_format_t::cbor, len) &&
10349                        get_binary(input_format_t::cbor, len, result);
10350             }
10351 
10352             case 0x59: // Binary data (two-byte uint16_t for n follow)
10353             {
10354                 std::uint16_t len{};
10355                 return get_number(input_format_t::cbor, len) &&
10356                        get_binary(input_format_t::cbor, len, result);
10357             }
10358 
10359             case 0x5A: // Binary data (four-byte uint32_t for n follow)
10360             {
10361                 std::uint32_t len{};
10362                 return get_number(input_format_t::cbor, len) &&
10363                        get_binary(input_format_t::cbor, len, result);
10364             }
10365 
10366             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10367             {
10368                 std::uint64_t len{};
10369                 return get_number(input_format_t::cbor, len) &&
10370                        get_binary(input_format_t::cbor, len, result);
10371             }
10372 
10373             case 0x5F: // Binary data (indefinite length)
10374             {
10375                 while (get() != 0xFF)
10376                 {
10377                     binary_t chunk;
10378                     if (!get_cbor_binary(chunk))
10379                     {
10380                         return false;
10381                     }
10382                     result.insert(result.end(), chunk.begin(), chunk.end());
10383                 }
10384                 return true;
10385             }
10386 
10387             default:
10388             {
10389                 auto last_token = get_token_string();
10390                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10391                                         exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10392             }
10393         }
10394     }
10395 
10396     /*! 
10397     @param[in] len  the length of the array or static_cast<std::size_t>(-1) for an 
10398                     array of indefinite size 
10399     @param[in] tag_handler how CBOR tags should be treated 
10400     @return whether array creation completed 
10401     */
10402     bool get_cbor_array(const std::size_t len,
10403                         const cbor_tag_handler_t tag_handler)
10404     {
10405         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10406         {
10407             return false;
10408         }
10409 
10410         if (len != static_cast<std::size_t>(-1))
10411         {
10412             for (std::size_t i = 0; i < len; ++i)
10413             {
10414                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10415                 {
10416                     return false;
10417                 }
10418             }
10419         }
10420         else
10421         {
10422             while (get() != 0xFF)
10423             {
10424                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10425                 {
10426                     return false;
10427                 }
10428             }
10429         }
10430 
10431         return sax->end_array();
10432     }
10433 
10434     /*! 
10435     @param[in] len  the length of the object or static_cast<std::size_t>(-1) for an 
10436                     object of indefinite size 
10437     @param[in] tag_handler how CBOR tags should be treated 
10438     @return whether object creation completed 
10439     */
10440     bool get_cbor_object(const std::size_t len,
10441                          const cbor_tag_handler_t tag_handler)
10442     {
10443         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10444         {
10445             return false;
10446         }
10447 
10448         if (len != 0)
10449         {
10450             string_t key;
10451             if (len != static_cast<std::size_t>(-1))
10452             {
10453                 for (std::size_t i = 0; i < len; ++i)
10454                 {
10455                     get();
10456                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10457                     {
10458                         return false;
10459                     }
10460 
10461                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10462                     {
10463                         return false;
10464                     }
10465                     key.clear();
10466                 }
10467             }
10468             else
10469             {
10470                 while (get() != 0xFF)
10471                 {
10472                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10473                     {
10474                         return false;
10475                     }
10476 
10477                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10478                     {
10479                         return false;
10480                     }
10481                     key.clear();
10482                 }
10483             }
10484         }
10485 
10486         return sax->end_object();
10487     }
10488 
10489     /////////////
10490     // MsgPack //
10491     /////////////
10492 
10493     /*! 
10494     @return whether a valid MessagePack value was passed to the SAX parser 
10495     */
10496     bool parse_msgpack_internal()
10497     {
10498         switch (get())
10499         {
10500             // EOF
10501             case char_traits<char_type>::eof():
10502                 return unexpect_eof(input_format_t::msgpack, "value");
10503 
10504             // positive fixint
10505             case 0x00:
10506             case 0x01:
10507             case 0x02:
10508             case 0x03:
10509             case 0x04:
10510             case 0x05:
10511             case 0x06:
10512             case 0x07:
10513             case 0x08:
10514             case 0x09:
10515             case 0x0A:
10516             case 0x0B:
10517             case 0x0C:
10518             case 0x0D:
10519             case 0x0E:
10520             case 0x0F:
10521             case 0x10:
10522             case 0x11:
10523             case 0x12:
10524             case 0x13:
10525             case 0x14:
10526             case 0x15:
10527             case 0x16:
10528             case 0x17:
10529             case 0x18:
10530             case 0x19:
10531             case 0x1A:
10532             case 0x1B:
10533             case 0x1C:
10534             case 0x1D:
10535             case 0x1E:
10536             case 0x1F:
10537             case 0x20:
10538             case 0x21:
10539             case 0x22:
10540             case 0x23:
10541             case 0x24:
10542             case 0x25:
10543             case 0x26:
10544             case 0x27:
10545             case 0x28:
10546             case 0x29:
10547             case 0x2A:
10548             case 0x2B:
10549             case 0x2C:
10550             case 0x2D:
10551             case 0x2E:
10552             case 0x2F:
10553             case 0x30:
10554             case 0x31:
10555             case 0x32:
10556             case 0x33:
10557             case 0x34:
10558             case 0x35:
10559             case 0x36:
10560             case 0x37:
10561             case 0x38:
10562             case 0x39:
10563             case 0x3A:
10564             case 0x3B:
10565             case 0x3C:
10566             case 0x3D:
10567             case 0x3E:
10568             case 0x3F:
10569             case 0x40:
10570             case 0x41:
10571             case 0x42:
10572             case 0x43:
10573             case 0x44:
10574             case 0x45:
10575             case 0x46:
10576             case 0x47:
10577             case 0x48:
10578             case 0x49:
10579             case 0x4A:
10580             case 0x4B:
10581             case 0x4C:
10582             case 0x4D:
10583             case 0x4E:
10584             case 0x4F:
10585             case 0x50:
10586             case 0x51:
10587             case 0x52:
10588             case 0x53:
10589             case 0x54:
10590             case 0x55:
10591             case 0x56:
10592             case 0x57:
10593             case 0x58:
10594             case 0x59:
10595             case 0x5A:
10596             case 0x5B:
10597             case 0x5C:
10598             case 0x5D:
10599             case 0x5E:
10600             case 0x5F:
10601             case 0x60:
10602             case 0x61:
10603             case 0x62:
10604             case 0x63:
10605             case 0x64:
10606             case 0x65:
10607             case 0x66:
10608             case 0x67:
10609             case 0x68:
10610             case 0x69:
10611             case 0x6A:
10612             case 0x6B:
10613             case 0x6C:
10614             case 0x6D:
10615             case 0x6E:
10616             case 0x6F:
10617             case 0x70:
10618             case 0x71:
10619             case 0x72:
10620             case 0x73:
10621             case 0x74:
10622             case 0x75:
10623             case 0x76:
10624             case 0x77:
10625             case 0x78:
10626             case 0x79:
10627             case 0x7A:
10628             case 0x7B:
10629             case 0x7C:
10630             case 0x7D:
10631             case 0x7E:
10632             case 0x7F:
10633                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10634 
10635             // fixmap
10636             case 0x80:
10637             case 0x81:
10638             case 0x82:
10639             case 0x83:
10640             case 0x84:
10641             case 0x85:
10642             case 0x86:
10643             case 0x87:
10644             case 0x88:
10645             case 0x89:
10646             case 0x8A:
10647             case 0x8B:
10648             case 0x8C:
10649             case 0x8D:
10650             case 0x8E:
10651             case 0x8F:
10652                 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10653 
10654             // fixarray
10655             case 0x90:
10656             case 0x91:
10657             case 0x92:
10658             case 0x93:
10659             case 0x94:
10660             case 0x95:
10661             case 0x96:
10662             case 0x97:
10663             case 0x98:
10664             case 0x99:
10665             case 0x9A:
10666             case 0x9B:
10667             case 0x9C:
10668             case 0x9D:
10669             case 0x9E:
10670             case 0x9F:
10671                 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10672 
10673             // fixstr
10674             case 0xA0:
10675             case 0xA1:
10676             case 0xA2:
10677             case 0xA3:
10678             case 0xA4:
10679             case 0xA5:
10680             case 0xA6:
10681             case 0xA7:
10682             case 0xA8:
10683             case 0xA9:
10684             case 0xAA:
10685             case 0xAB:
10686             case 0xAC:
10687             case 0xAD:
10688             case 0xAE:
10689             case 0xAF:
10690             case 0xB0:
10691             case 0xB1:
10692             case 0xB2:
10693             case 0xB3:
10694             case 0xB4:
10695             case 0xB5:
10696             case 0xB6:
10697             case 0xB7:
10698             case 0xB8:
10699             case 0xB9:
10700             case 0xBA:
10701             case 0xBB:
10702             case 0xBC:
10703             case 0xBD:
10704             case 0xBE:
10705             case 0xBF:
10706             case 0xD9: // str 8
10707             case 0xDA: // str 16
10708             case 0xDB: // str 32
10709             {
10710                 string_t s;
10711                 return get_msgpack_string(s) && sax->string(s);
10712             }
10713 
10714             case 0xC0: // nil
10715                 return sax->null();
10716 
10717             case 0xC2: // false
10718                 return sax->boolean(false);
10719 
10720             case 0xC3: // true
10721                 return sax->boolean(true);
10722 
10723             case 0xC4: // bin 8
10724             case 0xC5: // bin 16
10725             case 0xC6: // bin 32
10726             case 0xC7: // ext 8
10727             case 0xC8: // ext 16
10728             case 0xC9: // ext 32
10729             case 0xD4: // fixext 1
10730             case 0xD5: // fixext 2
10731             case 0xD6: // fixext 4
10732             case 0xD7: // fixext 8
10733             case 0xD8: // fixext 16
10734             {
10735                 binary_t b;
10736                 return get_msgpack_binary(b) && sax->binary(b);
10737             }
10738 
10739             case 0xCA: // float 32
10740             {
10741                 float number{};
10742                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10743             }
10744 
10745             case 0xCB: // float 64
10746             {
10747                 double number{};
10748                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10749             }
10750 
10751             case 0xCC: // uint 8
10752             {
10753                 std::uint8_t number{};
10754                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10755             }
10756 
10757             case 0xCD: // uint 16
10758             {
10759                 std::uint16_t number{};
10760                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10761             }
10762 
10763             case 0xCE: // uint 32
10764             {
10765                 std::uint32_t number{};
10766                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10767             }
10768 
10769             case 0xCF: // uint 64
10770             {
10771                 std::uint64_t number{};
10772                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10773             }
10774 
10775             case 0xD0: // int 8
10776             {
10777                 std::int8_t number{};
10778                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10779             }
10780 
10781             case 0xD1: // int 16
10782             {
10783                 std::int16_t number{};
10784                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10785             }
10786 
10787             case 0xD2: // int 32
10788             {
10789                 std::int32_t number{};
10790                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10791             }
10792 
10793             case 0xD3: // int 64
10794             {
10795                 std::int64_t number{};
10796                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10797             }
10798 
10799             case 0xDC: // array 16
10800             {
10801                 std::uint16_t len{};
10802                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10803             }
10804 
10805             case 0xDD: // array 32
10806             {
10807                 std::uint32_t len{};
10808                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10809             }
10810 
10811             case 0xDE: // map 16
10812             {
10813                 std::uint16_t len{};
10814                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10815             }
10816 
10817             case 0xDF: // map 32
10818             {
10819                 std::uint32_t len{};
10820                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10821             }
10822 
10823             // negative fixint
10824             case 0xE0:
10825             case 0xE1:
10826             case 0xE2:
10827             case 0xE3:
10828             case 0xE4:
10829             case 0xE5:
10830             case 0xE6:
10831             case 0xE7:
10832             case 0xE8:
10833             case 0xE9:
10834             case 0xEA:
10835             case 0xEB:
10836             case 0xEC:
10837             case 0xED:
10838             case 0xEE:
10839             case 0xEF:
10840             case 0xF0:
10841             case 0xF1:
10842             case 0xF2:
10843             case 0xF3:
10844             case 0xF4:
10845             case 0xF5:
10846             case 0xF6:
10847             case 0xF7:
10848             case 0xF8:
10849             case 0xF9:
10850             case 0xFA:
10851             case 0xFB:
10852             case 0xFC:
10853             case 0xFD:
10854             case 0xFE:
10855             case 0xFF:
10856                 return sax->number_integer(static_cast<std::int8_t>(current));
10857 
10858             default: // anything else
10859             {
10860                 auto last_token = get_token_string();
10861                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10862                                         exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10863             }
10864         }
10865     }
10866 
10867     /*! 
10868     @brief reads a MessagePack string 
10869  
10870     This function first reads starting bytes to determine the expected 
10871     string length and then copies this number of bytes into a string. 
10872  
10873     @param[out] result  created string 
10874  
10875     @return whether string creation completed 
10876     */
10877     bool get_msgpack_string(string_t& result)
10878     {
10879         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10880         {
10881             return false;
10882         }
10883 
10884         switch (current)
10885         {
10886             // fixstr
10887             case 0xA0:
10888             case 0xA1:
10889             case 0xA2:
10890             case 0xA3:
10891             case 0xA4:
10892             case 0xA5:
10893             case 0xA6:
10894             case 0xA7:
10895             case 0xA8:
10896             case 0xA9:
10897             case 0xAA:
10898             case 0xAB:
10899             case 0xAC:
10900             case 0xAD:
10901             case 0xAE:
10902             case 0xAF:
10903             case 0xB0:
10904             case 0xB1:
10905             case 0xB2:
10906             case 0xB3:
10907             case 0xB4:
10908             case 0xB5:
10909             case 0xB6:
10910             case 0xB7:
10911             case 0xB8:
10912             case 0xB9:
10913             case 0xBA:
10914             case 0xBB:
10915             case 0xBC:
10916             case 0xBD:
10917             case 0xBE:
10918             case 0xBF:
10919             {
10920                 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10921             }
10922 
10923             case 0xD9: // str 8
10924             {
10925                 std::uint8_t len{};
10926                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10927             }
10928 
10929             case 0xDA: // str 16
10930             {
10931                 std::uint16_t len{};
10932                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10933             }
10934 
10935             case 0xDB: // str 32
10936             {
10937                 std::uint32_t len{};
10938                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10939             }
10940 
10941             default:
10942             {
10943                 auto last_token = get_token_string();
10944                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10945                                         exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10946             }
10947         }
10948     }
10949 
10950     /*! 
10951     @brief reads a MessagePack byte array 
10952  
10953     This function first reads starting bytes to determine the expected 
10954     byte array length and then copies this number of bytes into a byte array. 
10955  
10956     @param[out] result  created byte array 
10957  
10958     @return whether byte array creation completed 
10959     */
10960     bool get_msgpack_binary(binary_t& result)
10961     {
10962         // helper function to set the subtype
10963         auto assign_and_return_true = [&result](std::int8_t subtype)
10964         {
10965             result.set_subtype(static_cast<std::uint8_t>(subtype));
10966             return true;
10967         };
10968 
10969         switch (current)
10970         {
10971             case 0xC4: // bin 8
10972             {
10973                 std::uint8_t len{};
10974                 return get_number(input_format_t::msgpack, len) &&
10975                        get_binary(input_format_t::msgpack, len, result);
10976             }
10977 
10978             case 0xC5: // bin 16
10979             {
10980                 std::uint16_t len{};
10981                 return get_number(input_format_t::msgpack, len) &&
10982                        get_binary(input_format_t::msgpack, len, result);
10983             }
10984 
10985             case 0xC6: // bin 32
10986             {
10987                 std::uint32_t len{};
10988                 return get_number(input_format_t::msgpack, len) &&
10989                        get_binary(input_format_t::msgpack, len, result);
10990             }
10991 
10992             case 0xC7: // ext 8
10993             {
10994                 std::uint8_t len{};
10995                 std::int8_t subtype{};
10996                 return get_number(input_format_t::msgpack, len) &&
10997                        get_number(input_format_t::msgpack, subtype) &&
10998                        get_binary(input_format_t::msgpack, len, result) &&
10999                        assign_and_return_true(subtype);
11000             }
11001 
11002             case 0xC8: // ext 16
11003             {
11004                 std::uint16_t len{};
11005                 std::int8_t subtype{};
11006                 return get_number(input_format_t::msgpack, len) &&
11007                        get_number(input_format_t::msgpack, subtype) &&
11008                        get_binary(input_format_t::msgpack, len, result) &&
11009                        assign_and_return_true(subtype);
11010             }
11011 
11012             case 0xC9: // ext 32
11013             {
11014                 std::uint32_t len{};
11015                 std::int8_t subtype{};
11016                 return get_number(input_format_t::msgpack, len) &&
11017                        get_number(input_format_t::msgpack, subtype) &&
11018                        get_binary(input_format_t::msgpack, len, result) &&
11019                        assign_and_return_true(subtype);
11020             }
11021 
11022             case 0xD4: // fixext 1
11023             {
11024                 std::int8_t subtype{};
11025                 return get_number(input_format_t::msgpack, subtype) &&
11026                        get_binary(input_format_t::msgpack, 1, result) &&
11027                        assign_and_return_true(subtype);
11028             }
11029 
11030             case 0xD5: // fixext 2
11031             {
11032                 std::int8_t subtype{};
11033                 return get_number(input_format_t::msgpack, subtype) &&
11034                        get_binary(input_format_t::msgpack, 2, result) &&
11035                        assign_and_return_true(subtype);
11036             }
11037 
11038             case 0xD6: // fixext 4
11039             {
11040                 std::int8_t subtype{};
11041                 return get_number(input_format_t::msgpack, subtype) &&
11042                        get_binary(input_format_t::msgpack, 4, result) &&
11043                        assign_and_return_true(subtype);
11044             }
11045 
11046             case 0xD7: // fixext 8
11047             {
11048                 std::int8_t subtype{};
11049                 return get_number(input_format_t::msgpack, subtype) &&
11050                        get_binary(input_format_t::msgpack, 8, result) &&
11051                        assign_and_return_true(subtype);
11052             }
11053 
11054             case 0xD8: // fixext 16
11055             {
11056                 std::int8_t subtype{};
11057                 return get_number(input_format_t::msgpack, subtype) &&
11058                        get_binary(input_format_t::msgpack, 16, result) &&
11059                        assign_and_return_true(subtype);
11060             }
11061 
11062             default:           // LCOV_EXCL_LINE
11063                 return false;  // LCOV_EXCL_LINE
11064         }
11065     }
11066 
11067     /*! 
11068     @param[in] len  the length of the array 
11069     @return whether array creation completed 
11070     */
11071     bool get_msgpack_array(const std::size_t len)
11072     {
11073         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11074         {
11075             return false;
11076         }
11077 
11078         for (std::size_t i = 0; i < len; ++i)
11079         {
11080             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11081             {
11082                 return false;
11083             }
11084         }
11085 
11086         return sax->end_array();
11087     }
11088 
11089     /*! 
11090     @param[in] len  the length of the object 
11091     @return whether object creation completed 
11092     */
11093     bool get_msgpack_object(const std::size_t len)
11094     {
11095         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11096         {
11097             return false;
11098         }
11099 
11100         string_t key;
11101         for (std::size_t i = 0; i < len; ++i)
11102         {
11103             get();
11104             if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11105             {
11106                 return false;
11107             }
11108 
11109             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11110             {
11111                 return false;
11112             }
11113             key.clear();
11114         }
11115 
11116         return sax->end_object();
11117     }
11118 
11119     ////////////
11120     // UBJSON //
11121     ////////////
11122 
11123     /*! 
11124     @param[in] get_char  whether a new character should be retrieved from the 
11125                          input (true, default) or whether the last read 
11126                          character should be considered instead 
11127  
11128     @return whether a valid UBJSON value was passed to the SAX parser 
11129     */
11130     bool parse_ubjson_internal(const bool get_char = true)
11131     {
11132         return get_ubjson_value(get_char ? get_ignore_noop() : current);
11133     }
11134 
11135     /*! 
11136     @brief reads a UBJSON string 
11137  
11138     This function is either called after reading the 'S' byte explicitly 
11139     indicating a string, or in case of an object key where the 'S' byte can be 
11140     left out. 
11141  
11142     @param[out] result   created string 
11143     @param[in] get_char  whether a new character should be retrieved from the 
11144                          input (true, default) or whether the last read 
11145                          character should be considered instead 
11146  
11147     @return whether string creation completed 
11148     */
11149     bool get_ubjson_string(string_t& result, const bool get_char = true)
11150     {
11151         if (get_char)
11152         {
11153             get();  // TODO(niels): may we ignore N here?
11154         }
11155 
11156         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11157         {
11158             return false;
11159         }
11160 
11161         switch (current)
11162         {
11163             case 'U':
11164             {
11165                 std::uint8_t len{};
11166                 return get_number(input_format, len) && get_string(input_format, len, result);
11167             }
11168 
11169             case 'i':
11170             {
11171                 std::int8_t len{};
11172                 return get_number(input_format, len) && get_string(input_format, len, result);
11173             }
11174 
11175             case 'I':
11176             {
11177                 std::int16_t len{};
11178                 return get_number(input_format, len) && get_string(input_format, len, result);
11179             }
11180 
11181             case 'l':
11182             {
11183                 std::int32_t len{};
11184                 return get_number(input_format, len) && get_string(input_format, len, result);
11185             }
11186 
11187             case 'L':
11188             {
11189                 std::int64_t len{};
11190                 return get_number(input_format, len) && get_string(input_format, len, result);
11191             }
11192 
11193             case 'u':
11194             {
11195                 if (input_format != input_format_t::bjdata)
11196                 {
11197                     break;
11198                 }
11199                 std::uint16_t len{};
11200                 return get_number(input_format, len) && get_string(input_format, len, result);
11201             }
11202 
11203             case 'm':
11204             {
11205                 if (input_format != input_format_t::bjdata)
11206                 {
11207                     break;
11208                 }
11209                 std::uint32_t len{};
11210                 return get_number(input_format, len) && get_string(input_format, len, result);
11211             }
11212 
11213             case 'M':
11214             {
11215                 if (input_format != input_format_t::bjdata)
11216                 {
11217                     break;
11218                 }
11219                 std::uint64_t len{};
11220                 return get_number(input_format, len) && get_string(input_format, len, result);
11221             }
11222 
11223             default:
11224                 break;
11225         }
11226         auto last_token = get_token_string();
11227         std::string message;
11228 
11229         if (input_format != input_format_t::bjdata)
11230         {
11231             message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11232         }
11233         else
11234         {
11235             message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11236         }
11237         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11238     }
11239 
11240     /*! 
11241     @param[out] dim  an integer vector storing the ND array dimensions 
11242     @return whether reading ND array size vector is successful 
11243     */
11244     bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11245     {
11246         std::pair<std::size_t, char_int_type> size_and_type;
11247         size_t dimlen = 0;
11248         bool no_ndarray = true;
11249 
11250         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11251         {
11252             return false;
11253         }
11254 
11255         if (size_and_type.first != npos)
11256         {
11257             if (size_and_type.second != 0)
11258             {
11259                 if (size_and_type.second != 'N')
11260                 {
11261                     for (std::size_t i = 0; i < size_and_type.first; ++i)
11262                     {
11263                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11264                         {
11265                             return false;
11266                         }
11267                         dim.push_back(dimlen);
11268                     }
11269                 }
11270             }
11271             else
11272             {
11273                 for (std::size_t i = 0; i < size_and_type.first; ++i)
11274                 {
11275                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11276                     {
11277                         return false;
11278                     }
11279                     dim.push_back(dimlen);
11280                 }
11281             }
11282         }
11283         else
11284         {
11285             while (current != ']')
11286             {
11287                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11288                 {
11289                     return false;
11290                 }
11291                 dim.push_back(dimlen);
11292                 get_ignore_noop();
11293             }
11294         }
11295         return true;
11296     }
11297 
11298     /*! 
11299     @param[out] result  determined size 
11300     @param[in,out] is_ndarray  for input, `true` means already inside an ndarray vector 
11301                                or ndarray dimension is not allowed; `false` means ndarray 
11302                                is allowed; for output, `true` means an ndarray is found; 
11303                                is_ndarray can only return `true` when its initial value 
11304                                is `false` 
11305     @param[in] prefix  type marker if already read, otherwise set to 0 
11306  
11307     @return whether size determination completed 
11308     */
11309     bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11310     {
11311         if (prefix == 0)
11312         {
11313             prefix = get_ignore_noop();
11314         }
11315 
11316         switch (prefix)
11317         {
11318             case 'U':
11319             {
11320                 std::uint8_t number{};
11321                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11322                 {
11323                     return false;
11324                 }
11325                 result = static_cast<std::size_t>(number);
11326                 return true;
11327             }
11328 
11329             case 'i':
11330             {
11331                 std::int8_t number{};
11332                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11333                 {
11334                     return false;
11335                 }
11336                 if (number < 0)
11337                 {
11338                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11339                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11340                 }
11341                 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11342                 return true;
11343             }
11344 
11345             case 'I':
11346             {
11347                 std::int16_t number{};
11348                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11349                 {
11350                     return false;
11351                 }
11352                 if (number < 0)
11353                 {
11354                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11355                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11356                 }
11357                 result = static_cast<std::size_t>(number);
11358                 return true;
11359             }
11360 
11361             case 'l':
11362             {
11363                 std::int32_t number{};
11364                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11365                 {
11366                     return false;
11367                 }
11368                 if (number < 0)
11369                 {
11370                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11371                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11372                 }
11373                 result = static_cast<std::size_t>(number);
11374                 return true;
11375             }
11376 
11377             case 'L':
11378             {
11379                 std::int64_t number{};
11380                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11381                 {
11382                     return false;
11383                 }
11384                 if (number < 0)
11385                 {
11386                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11387                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11388                 }
11389                 if (!value_in_range_of<std::size_t>(number))
11390                 {
11391                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11392                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
11393                 }
11394                 result = static_cast<std::size_t>(number);
11395                 return true;
11396             }
11397 
11398             case 'u':
11399             {
11400                 if (input_format != input_format_t::bjdata)
11401                 {
11402                     break;
11403                 }
11404                 std::uint16_t number{};
11405                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11406                 {
11407                     return false;
11408                 }
11409                 result = static_cast<std::size_t>(number);
11410                 return true;
11411             }
11412 
11413             case 'm':
11414             {
11415                 if (input_format != input_format_t::bjdata)
11416                 {
11417                     break;
11418                 }
11419                 std::uint32_t number{};
11420                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11421                 {
11422                     return false;
11423                 }
11424                 result = conditional_static_cast<std::size_t>(number);
11425                 return true;
11426             }
11427 
11428             case 'M':
11429             {
11430                 if (input_format != input_format_t::bjdata)
11431                 {
11432                     break;
11433                 }
11434                 std::uint64_t number{};
11435                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11436                 {
11437                     return false;
11438                 }
11439                 if (!value_in_range_of<std::size_t>(number))
11440                 {
11441                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11442                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
11443                 }
11444                 result = detail::conditional_static_cast<std::size_t>(number);
11445                 return true;
11446             }
11447 
11448             case '[':
11449             {
11450                 if (input_format != input_format_t::bjdata)
11451                 {
11452                     break;
11453                 }
11454                 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11455                 {
11456                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11457                 }
11458                 std::vector<size_t> dim;
11459                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11460                 {
11461                     return false;
11462                 }
11463                 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11464                 {
11465                     result = dim.at(dim.size() - 1);
11466                     return true;
11467                 }
11468                 if (!dim.empty())  // if ndarray, convert to an object in JData annotated array format
11469                 {
11470                     for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11471                     {
11472                         if ( i == 0 )
11473                         {
11474                             result = 0;
11475                             return true;
11476                         }
11477                     }
11478 
11479                     string_t key = "_ArraySize_";
11480                     if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11481                     {
11482                         return false;
11483                     }
11484                     result = 1;
11485                     for (auto i : dim)
11486                     {
11487                         result *= i;
11488                         if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11489                         {
11490                             return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
11491                         }
11492                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11493                         {
11494                             return false;
11495                         }
11496                     }
11497                     is_ndarray = true;
11498                     return sax->end_array();
11499                 }
11500                 result = 0;
11501                 return true;
11502             }
11503 
11504             default:
11505                 break;
11506         }
11507         auto last_token = get_token_string();
11508         std::string message;
11509 
11510         if (input_format != input_format_t::bjdata)
11511         {
11512             message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11513         }
11514         else
11515         {
11516             message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11517         }
11518         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11519     }
11520 
11521     /*! 
11522     @brief determine the type and size for a container 
11523  
11524     In the optimized UBJSON format, a type and a size can be provided to allow 
11525     for a more compact representation. 
11526  
11527     @param[out] result  pair of the size and the type 
11528     @param[in] inside_ndarray  whether the parser is parsing an ND array dimensional vector 
11529  
11530     @return whether pair creation completed 
11531     */
11532     bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11533     {
11534         result.first = npos; // size
11535         result.second = 0; // type
11536         bool is_ndarray = false;
11537 
11538         get_ignore_noop();
11539 
11540         if (current == '$')
11541         {
11542             result.second = get();  // must not ignore 'N', because 'N' maybe the type
11543             if (input_format == input_format_t::bjdata
11544                     && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11545             {
11546                 auto last_token = get_token_string();
11547                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11548                                         exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11549             }
11550 
11551             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11552             {
11553                 return false;
11554             }
11555 
11556             get_ignore_noop();
11557             if (JSON_HEDLEY_UNLIKELY(current != '#'))
11558             {
11559                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11560                 {
11561                     return false;
11562                 }
11563                 auto last_token = get_token_string();
11564                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11565                                         exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11566             }
11567 
11568             const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11569             if (input_format == input_format_t::bjdata && is_ndarray)
11570             {
11571                 if (inside_ndarray)
11572                 {
11573                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11574                                             exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11575                 }
11576                 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11577             }
11578             return is_error;
11579         }
11580 
11581         if (current == '#')
11582         {
11583             const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11584             if (input_format == input_format_t::bjdata && is_ndarray)
11585             {
11586                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11587                                         exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11588             }
11589             return is_error;
11590         }
11591 
11592         return true;
11593     }
11594 
11595     /*! 
11596     @param prefix  the previously read or set type prefix 
11597     @return whether value creation completed 
11598     */
11599     bool get_ubjson_value(const char_int_type prefix)
11600     {
11601         switch (prefix)
11602         {
11603             case char_traits<char_type>::eof():  // EOF
11604                 return unexpect_eof(input_format, "value");
11605 
11606             case 'T':  // true
11607                 return sax->boolean(true);
11608             case 'F':  // false
11609                 return sax->boolean(false);
11610 
11611             case 'Z':  // null
11612                 return sax->null();
11613 
11614             case 'U':
11615             {
11616                 std::uint8_t number{};
11617                 return get_number(input_format, number) && sax->number_unsigned(number);
11618             }
11619 
11620             case 'i':
11621             {
11622                 std::int8_t number{};
11623                 return get_number(input_format, number) && sax->number_integer(number);
11624             }
11625 
11626             case 'I':
11627             {
11628                 std::int16_t number{};
11629                 return get_number(input_format, number) && sax->number_integer(number);
11630             }
11631 
11632             case 'l':
11633             {
11634                 std::int32_t number{};
11635                 return get_number(input_format, number) && sax->number_integer(number);
11636             }
11637 
11638             case 'L':
11639             {
11640                 std::int64_t number{};
11641                 return get_number(input_format, number) && sax->number_integer(number);
11642             }
11643 
11644             case 'u':
11645             {
11646                 if (input_format != input_format_t::bjdata)
11647                 {
11648                     break;
11649                 }
11650                 std::uint16_t number{};
11651                 return get_number(input_format, number) && sax->number_unsigned(number);
11652             }
11653 
11654             case 'm':
11655             {
11656                 if (input_format != input_format_t::bjdata)
11657                 {
11658                     break;
11659                 }
11660                 std::uint32_t number{};
11661                 return get_number(input_format, number) && sax->number_unsigned(number);
11662             }
11663 
11664             case 'M':
11665             {
11666                 if (input_format != input_format_t::bjdata)
11667                 {
11668                     break;
11669                 }
11670                 std::uint64_t number{};
11671                 return get_number(input_format, number) && sax->number_unsigned(number);
11672             }
11673 
11674             case 'h':
11675             {
11676                 if (input_format != input_format_t::bjdata)
11677                 {
11678                     break;
11679                 }
11680                 const auto byte1_raw = get();
11681                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11682                 {
11683                     return false;
11684                 }
11685                 const auto byte2_raw = get();
11686                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11687                 {
11688                     return false;
11689                 }
11690 
11691                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11692                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11693 
11694                 // code from RFC 7049, Appendix D, Figure 3:
11695                 // As half-precision floating-point numbers were only added
11696                 // to IEEE 754 in 2008, today's programming platforms often
11697                 // still only have limited support for them. It is very
11698                 // easy to include at least decoding support for them even
11699                 // without such support. An example of a small decoder for
11700                 // half-precision floating-point numbers in the C language
11701                 // is shown in Fig. 3.
11702                 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11703                 const double val = [&half]
11704                 {
11705                     const int exp = (half >> 10u) & 0x1Fu;
11706                     const unsigned int mant = half & 0x3FFu;
11707                     JSON_ASSERT(0 <= exp&& exp <= 32);
11708                     JSON_ASSERT(mant <= 1024);
11709                     switch (exp)
11710                     {
11711                         case 0:
11712                             return std::ldexp(mant, -24);
11713                         case 31:
11714                             return (mant == 0)
11715                             ? std::numeric_limits<double>::infinity()
11716                             : std::numeric_limits<double>::quiet_NaN();
11717                         default:
11718                             return std::ldexp(mant + 1024, exp - 25);
11719                     }
11720                 }();
11721                 return sax->number_float((half & 0x8000u) != 0
11722                                          ? static_cast<number_float_t>(-val)
11723                                          : static_cast<number_float_t>(val), "");
11724             }
11725 
11726             case 'd':
11727             {
11728                 float number{};
11729                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11730             }
11731 
11732             case 'D':
11733             {
11734                 double number{};
11735                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11736             }
11737 
11738             case 'H':
11739             {
11740                 return get_ubjson_high_precision_number();
11741             }
11742 
11743             case 'C':  // char
11744             {
11745                 get();
11746                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11747                 {
11748                     return false;
11749                 }
11750                 if (JSON_HEDLEY_UNLIKELY(current > 127))
11751                 {
11752                     auto last_token = get_token_string();
11753                     return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11754                                             exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11755                 }
11756                 string_t s(1, static_cast<typename string_t::value_type>(current));
11757                 return sax->string(s);
11758             }
11759 
11760             case 'S':  // string
11761             {
11762                 string_t s;
11763                 return get_ubjson_string(s) && sax->string(s);
11764             }
11765 
11766             case '[':  // array
11767                 return get_ubjson_array();
11768 
11769             case '{':  // object
11770                 return get_ubjson_object();
11771 
11772             default: // anything else
11773                 break;
11774         }
11775         auto last_token = get_token_string();
11776         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11777     }
11778 
11779     /*! 
11780     @return whether array creation completed 
11781     */
11782     bool get_ubjson_array()
11783     {
11784         std::pair<std::size_t, char_int_type> size_and_type;
11785         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11786         {
11787             return false;
11788         }
11789 
11790         // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11791         // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11792 
11793         if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11794         {
11795             size_and_type.second &= ~(static_cast<char_int_type>(1) << 8);  // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11796             auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
11797             {
11798                 return p.first < t;
11799             });
11800             string_t key = "_ArrayType_";
11801             if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11802             {
11803                 auto last_token = get_token_string();
11804                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11805                                         exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11806             }
11807 
11808             string_t type = it->second; // sax->string() takes a reference
11809             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11810             {
11811                 return false;
11812             }
11813 
11814             if (size_and_type.second == 'C')
11815             {
11816                 size_and_type.second = 'U';
11817             }
11818 
11819             key = "_ArrayData_";
11820             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11821             {
11822                 return false;
11823             }
11824 
11825             for (std::size_t i = 0; i < size_and_type.first; ++i)
11826             {
11827                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11828                 {
11829                     return false;
11830                 }
11831             }
11832 
11833             return (sax->end_array() && sax->end_object());
11834         }
11835 
11836         if (size_and_type.first != npos)
11837         {
11838             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11839             {
11840                 return false;
11841             }
11842 
11843             if (size_and_type.second != 0)
11844             {
11845                 if (size_and_type.second != 'N')
11846                 {
11847                     for (std::size_t i = 0; i < size_and_type.first; ++i)
11848                     {
11849                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11850                         {
11851                             return false;
11852                         }
11853                     }
11854                 }
11855             }
11856             else
11857             {
11858                 for (std::size_t i = 0; i < size_and_type.first; ++i)
11859                 {
11860                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11861                     {
11862                         return false;
11863                     }
11864                 }
11865             }
11866         }
11867         else
11868         {
11869             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11870             {
11871                 return false;
11872             }
11873 
11874             while (current != ']')
11875             {
11876                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11877                 {
11878                     return false;
11879                 }
11880                 get_ignore_noop();
11881             }
11882         }
11883 
11884         return sax->end_array();
11885     }
11886 
11887     /*! 
11888     @return whether object creation completed 
11889     */
11890     bool get_ubjson_object()
11891     {
11892         std::pair<std::size_t, char_int_type> size_and_type;
11893         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11894         {
11895             return false;
11896         }
11897 
11898         // do not accept ND-array size in objects in BJData
11899         if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11900         {
11901             auto last_token = get_token_string();
11902             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11903                                     exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11904         }
11905 
11906         string_t key;
11907         if (size_and_type.first != npos)
11908         {
11909             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11910             {
11911                 return false;
11912             }
11913 
11914             if (size_and_type.second != 0)
11915             {
11916                 for (std::size_t i = 0; i < size_and_type.first; ++i)
11917                 {
11918                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11919                     {
11920                         return false;
11921                     }
11922                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11923                     {
11924                         return false;
11925                     }
11926                     key.clear();
11927                 }
11928             }
11929             else
11930             {
11931                 for (std::size_t i = 0; i < size_and_type.first; ++i)
11932                 {
11933                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11934                     {
11935                         return false;
11936                     }
11937                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11938                     {
11939                         return false;
11940                     }
11941                     key.clear();
11942                 }
11943             }
11944         }
11945         else
11946         {
11947             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11948             {
11949                 return false;
11950             }
11951 
11952             while (current != '}')
11953             {
11954                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11955                 {
11956                     return false;
11957                 }
11958                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11959                 {
11960                     return false;
11961                 }
11962                 get_ignore_noop();
11963                 key.clear();
11964             }
11965         }
11966 
11967         return sax->end_object();
11968     }
11969 
11970     // Note, no reader for UBJSON binary types is implemented because they do
11971     // not exist
11972 
11973     bool get_ubjson_high_precision_number()
11974     {
11975         // get size of following number string
11976         std::size_t size{};
11977         bool no_ndarray = true;
11978         auto res = get_ubjson_size_value(size, no_ndarray);
11979         if (JSON_HEDLEY_UNLIKELY(!res))
11980         {
11981             return res;
11982         }
11983 
11984         // get number string
11985         std::vector<char> number_vector;
11986         for (std::size_t i = 0; i < size; ++i)
11987         {
11988             get();
11989             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11990             {
11991                 return false;
11992             }
11993             number_vector.push_back(static_cast<char>(current));
11994         }
11995 
11996         // parse number string
11997         using ia_type = decltype(detail::input_adapter(number_vector));
11998         auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11999         const auto result_number = number_lexer.scan();
12000         const auto number_string = number_lexer.get_token_string();
12001         const auto result_remainder = number_lexer.scan();
12002 
12003         using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12004 
12005         if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12006         {
12007             return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12008                                     exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12009         }
12010 
12011         switch (result_number)
12012         {
12013             case token_type::value_integer:
12014                 return sax->number_integer(number_lexer.get_number_integer());
12015             case token_type::value_unsigned:
12016                 return sax->number_unsigned(number_lexer.get_number_unsigned());
12017             case token_type::value_float:
12018                 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12019             case token_type::uninitialized:
12020             case token_type::literal_true:
12021             case token_type::literal_false:
12022             case token_type::literal_null:
12023             case token_type::value_string:
12024             case token_type::begin_array:
12025             case token_type::begin_object:
12026             case token_type::end_array:
12027             case token_type::end_object:
12028             case token_type::name_separator:
12029             case token_type::value_separator:
12030             case token_type::parse_error:
12031             case token_type::end_of_input:
12032             case token_type::literal_or_value:
12033             default:
12034                 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12035                                         exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12036         }
12037     }
12038 
12039     ///////////////////////
12040     // Utility functions //
12041     ///////////////////////
12042 
12043     /*! 
12044     @brief get next character from the input 
12045  
12046     This function provides the interface to the used input adapter. It does 
12047     not throw in case the input reached EOF, but returns a -'ve valued 
12048     `char_traits<char_type>::eof()` in that case. 
12049  
12050     @return character read from the input 
12051     */
12052     char_int_type get()
12053     {
12054         ++chars_read;
12055         return current = ia.get_character();
12056     }
12057 
12058     /*! 
12059     @brief get_to read into a primitive type 
12060  
12061     This function provides the interface to the used input adapter. It does 
12062     not throw in case the input reached EOF, but returns false instead 
12063  
12064     @return bool, whether the read was successful 
12065     */
12066     template<class T>
12067     bool get_to(T& dest, const input_format_t format, const char* context)
12068     {
12069         auto new_chars_read = ia.get_elements(&dest);
12070         chars_read += new_chars_read;
12071         if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12072         {
12073             // in case of failure, advance position by 1 to report failing location
12074             ++chars_read;
12075             sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12076             return false;
12077         }
12078         return true;
12079     }
12080 
12081     /*! 
12082     @return character read from the input after ignoring all 'N' entries 
12083     */
12084     char_int_type get_ignore_noop()
12085     {
12086         do
12087         {
12088             get();
12089         }
12090         while (current == 'N');
12091 
12092         return current;
12093     }
12094 
12095     template<class NumberType>
12096     static void byte_swap(NumberType& number)
12097     {
12098         constexpr std::size_t sz = sizeof(number);
12099 #ifdef __cpp_lib_byteswap
12100         if constexpr (sz == 1)
12101         {
12102             return;
12103         }
12104         if constexpr(std::is_integral_v<NumberType>)
12105         {
12106             number = std::byteswap(number);
12107             return;
12108         }
12109 #endif
12110         auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12111         for (std::size_t i = 0; i < sz / 2; ++i)
12112         {
12113             std::swap(ptr[i], ptr[sz - i - 1]);
12114         }
12115     }
12116 
12117     /* 
12118     @brief read a number from the input 
12119  
12120     @tparam NumberType the type of the number 
12121     @param[in] format   the current format (for diagnostics) 
12122     @param[out] result  number of type @a NumberType 
12123  
12124     @return whether conversion completed 
12125  
12126     @note This function needs to respect the system's endianness, because 
12127           bytes in CBOR, MessagePack, and UBJSON are stored in network order 
12128           (big endian) and therefore need reordering on little endian systems. 
12129           On the other hand, BSON and BJData use little endian and should reorder 
12130           on big endian systems. 
12131     */
12132     template<typename NumberType, bool InputIsLittleEndian = false>
12133     bool get_number(const input_format_t format, NumberType& result)
12134     {
12135         // read in the original format
12136 
12137         if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12138         {
12139             return false;
12140         }
12141         if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12142         {
12143             byte_swap(result);
12144         }
12145         return true;
12146     }
12147 
12148     /*! 
12149     @brief create a string by reading characters from the input 
12150  
12151     @tparam NumberType the type of the number 
12152     @param[in] format the current format (for diagnostics) 
12153     @param[in] len number of characters to read 
12154     @param[out] result string created by reading @a len bytes 
12155  
12156     @return whether string creation completed 
12157  
12158     @note We can not reserve @a len bytes for the result, because @a len 
12159           may be too large. Usually, @ref unexpect_eof() detects the end of 
12160           the input before we run out of string memory. 
12161     */
12162     template<typename NumberType>
12163     bool get_string(const input_format_t format,
12164                     const NumberType len,
12165                     string_t& result)
12166     {
12167         bool success = true;
12168         for (NumberType i = 0; i < len; i++)
12169         {
12170             get();
12171             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12172             {
12173                 success = false;
12174                 break;
12175             }
12176             result.push_back(static_cast<typename string_t::value_type>(current));
12177         }
12178         return success;
12179     }
12180 
12181     /*! 
12182     @brief create a byte array by reading bytes from the input 
12183  
12184     @tparam NumberType the type of the number 
12185     @param[in] format the current format (for diagnostics) 
12186     @param[in] len number of bytes to read 
12187     @param[out] result byte array created by reading @a len bytes 
12188  
12189     @return whether byte array creation completed 
12190  
12191     @note We can not reserve @a len bytes for the result, because @a len 
12192           may be too large. Usually, @ref unexpect_eof() detects the end of 
12193           the input before we run out of memory. 
12194     */
12195     template<typename NumberType>
12196     bool get_binary(const input_format_t format,
12197                     const NumberType len,
12198                     binary_t& result)
12199     {
12200         bool success = true;
12201         for (NumberType i = 0; i < len; i++)
12202         {
12203             get();
12204             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12205             {
12206                 success = false;
12207                 break;
12208             }
12209             result.push_back(static_cast<std::uint8_t>(current));
12210         }
12211         return success;
12212     }
12213 
12214     /*! 
12215     @param[in] format   the current format (for diagnostics) 
12216     @param[in] context  further context information (for diagnostics) 
12217     @return whether the last read character is not EOF 
12218     */
12219     JSON_HEDLEY_NON_NULL(3)
12220     bool unexpect_eof(const input_format_t format, const char* context) const
12221     {
12222         if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12223         {
12224             return sax->parse_error(chars_read, "<end of file>",
12225                                     parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12226         }
12227         return true;
12228     }
12229 
12230     /*! 
12231     @return a string representation of the last read byte 
12232     */
12233     std::string get_token_string() const
12234     {
12235         std::array<char, 3> cr{{}};
12236         static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12237         return std::string{cr.data()};
12238     }
12239 
12240     /*! 
12241     @param[in] format   the current format 
12242     @param[in] detail   a detailed error message 
12243     @param[in] context  further context information 
12244     @return a message string to use in the parse_error exceptions 
12245     */
12246     std::string exception_message(const input_format_t format,
12247                                   const std::string& detail,
12248                                   const std::string& context) const
12249     {
12250         std::string error_msg = "syntax error while parsing ";
12251 
12252         switch (format)
12253         {
12254             case input_format_t::cbor:
12255                 error_msg += "CBOR";
12256                 break;
12257 
12258             case input_format_t::msgpack:
12259                 error_msg += "MessagePack";
12260                 break;
12261 
12262             case input_format_t::ubjson:
12263                 error_msg += "UBJSON";
12264                 break;
12265 
12266             case input_format_t::bson:
12267                 error_msg += "BSON";
12268                 break;
12269 
12270             case input_format_t::bjdata:
12271                 error_msg += "BJData";
12272                 break;
12273 
12274             case input_format_t::json: // LCOV_EXCL_LINE
12275             default:            // LCOV_EXCL_LINE
12276                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12277         }
12278 
12279         return concat(error_msg, ' ', context, ": ", detail);
12280     }
12281 
12282   private:
12283     static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12284 
12285     /// input adapter
12286     InputAdapterType ia;
12287 
12288     /// the current character
12289     char_int_type current = char_traits<char_type>::eof();
12290 
12291     /// the number of characters read
12292     std::size_t chars_read = 0;
12293 
12294     /// whether we can assume little endianness
12295     const bool is_little_endian = little_endianness();
12296 
12297     /// input format
12298     const input_format_t input_format = input_format_t::json;
12299 
12300     /// the SAX parser
12301     json_sax_t* sax = nullptr;
12302 
12303     // excluded markers in bjdata optimized type
12304 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ 
12305     make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12306 
12307 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ 
12308     make_array<bjd_type>(                      \ 
12309     bjd_type{'C', "char"},                     \ 
12310     bjd_type{'D', "double"},                   \ 
12311     bjd_type{'I', "int16"},                    \ 
12312     bjd_type{'L', "int64"},                    \ 
12313     bjd_type{'M', "uint64"},                   \ 
12314     bjd_type{'U', "uint8"},                    \ 
12315     bjd_type{'d', "single"},                   \ 
12316     bjd_type{'i', "int8"},                     \ 
12317     bjd_type{'l', "int32"},                    \ 
12318     bjd_type{'m', "uint32"},                   \ 
12319     bjd_type{'u', "uint16"})
12320 
12321   JSON_PRIVATE_UNLESS_TESTED:
12322     // lookup tables
12323     // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12324     const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12325         JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12326 
12327     using bjd_type = std::pair<char_int_type, string_t>;
12328     // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12329     const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12330         JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12331 
12332 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12333 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12334 };
12335 
12336 #ifndef JSON_HAS_CPP_17
12337     template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12338     constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12339 #endif
12340 
12341 }  // namespace detail
12342 NLOHMANN_JSON_NAMESPACE_END
12343 
12344 // #include <nlohmann/detail/input/input_adapters.hpp>
12345 
12346 // #include <nlohmann/detail/input/lexer.hpp>
12347 
12348 // #include <nlohmann/detail/input/parser.hpp>
12349 //     __ _____ _____ _____
12350 //  __|  |   __|     |   | |  JSON for Modern C++
12351 // |  |  |__   |  |  | | | |  version 3.11.3
12352 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
12353 //
12354 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
12355 // SPDX-License-Identifier: MIT
12356 
12357 
12358 
12359 #include <cmath> // isfinite
12360 #include <cstdint> // uint8_t
12361 #include <functional> // function
12362 #include <string> // string
12363 #include <utility> // move
12364 #include <vector> // vector
12365 
12366 // #include <nlohmann/detail/exceptions.hpp>
12367 
12368 // #include <nlohmann/detail/input/input_adapters.hpp>
12369 
12370 // #include <nlohmann/detail/input/json_sax.hpp>
12371 
12372 // #include <nlohmann/detail/input/lexer.hpp>
12373 
12374 // #include <nlohmann/detail/macro_scope.hpp>
12375 
12376 // #include <nlohmann/detail/meta/is_sax.hpp>
12377 
12378 // #include <nlohmann/detail/string_concat.hpp>
12379 
12380 // #include <nlohmann/detail/value_t.hpp>
12381 
12382 
12383 NLOHMANN_JSON_NAMESPACE_BEGIN
12384 namespace detail
12385 {
12386 ////////////
12387 // parser //
12388 ////////////
12389 
12390 enum class parse_event_t : std::uint8_t
12391 {
12392     /// the parser read `{` and started to process a JSON object
12393     object_start,
12394     /// the parser read `}` and finished processing a JSON object
12395     object_end,
12396     /// the parser read `[` and started to process a JSON array
12397     array_start,
12398     /// the parser read `]` and finished processing a JSON array
12399     array_end,
12400     /// the parser read a key of a value in an object
12401     key,
12402     /// the parser finished reading a JSON value
12403     value
12404 };
12405 
12406 template<typename BasicJsonType>
12407 using parser_callback_t =
12408     std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12409 
12410 /*! 
12411 @brief syntax analysis 
12412  
12413 This class implements a recursive descent parser. 
12414 */
12415 template<typename BasicJsonType, typename InputAdapterType>
12416 class parser
12417 {
12418     using number_integer_t = typename BasicJsonType::number_integer_t;
12419     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12420     using number_float_t = typename BasicJsonType::number_float_t;
12421     using string_t = typename BasicJsonType::string_t;
12422     using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12423     using token_type = typename lexer_t::token_type;
12424 
12425   public:
12426     /// a parser reading from an input adapter
12427     explicit parser(InputAdapterType&& adapter,
12428                     parser_callback_t<BasicJsonType> cb = nullptr,
12429                     const bool allow_exceptions_ = true,
12430                     const bool skip_comments = false)
12431         : callback(std::move(cb))
12432         , m_lexer(std::move(adapter), skip_comments)
12433         , allow_exceptions(allow_exceptions_)
12434     {
12435         // read first token
12436         get_token();
12437     }
12438 
12439     /*! 
12440     @brief public parser interface 
12441  
12442     @param[in] strict      whether to expect the last token to be EOF 
12443     @param[in,out] result  parsed JSON value 
12444  
12445     @throw parse_error.101 in case of an unexpected token 
12446     @throw parse_error.102 if to_unicode fails or surrogate error 
12447     @throw parse_error.103 if to_unicode fails 
12448     */
12449     void parse(const bool strict, BasicJsonType& result)
12450     {
12451         if (callback)
12452         {
12453             json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12454             sax_parse_internal(&sdp);
12455 
12456             // in strict mode, input must be completely read
12457             if (strict && (get_token() != token_type::end_of_input))
12458             {
12459                 sdp.parse_error(m_lexer.get_position(),
12460                                 m_lexer.get_token_string(),
12461                                 parse_error::create(101, m_lexer.get_position(),
12462                                                     exception_message(token_type::end_of_input, "value"), nullptr));
12463             }
12464 
12465             // in case of an error, return discarded value
12466             if (sdp.is_errored())
12467             {
12468                 result = value_t::discarded;
12469                 return;
12470             }
12471 
12472             // set top-level value to null if it was discarded by the callback
12473             // function
12474             if (result.is_discarded())
12475             {
12476                 result = nullptr;
12477             }
12478         }
12479         else
12480         {
12481             json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12482             sax_parse_internal(&sdp);
12483 
12484             // in strict mode, input must be completely read
12485             if (strict && (get_token() != token_type::end_of_input))
12486             {
12487                 sdp.parse_error(m_lexer.get_position(),
12488                                 m_lexer.get_token_string(),
12489                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12490             }
12491 
12492             // in case of an error, return discarded value
12493             if (sdp.is_errored())
12494             {
12495                 result = value_t::discarded;
12496                 return;
12497             }
12498         }
12499 
12500         result.assert_invariant();
12501     }
12502 
12503     /*! 
12504     @brief public accept interface 
12505  
12506     @param[in] strict  whether to expect the last token to be EOF 
12507     @return whether the input is a proper JSON text 
12508     */
12509     bool accept(const bool strict = true)
12510     {
12511         json_sax_acceptor<BasicJsonType> sax_acceptor;
12512         return sax_parse(&sax_acceptor, strict);
12513     }
12514 
12515     template<typename SAX>
12516     JSON_HEDLEY_NON_NULL(2)
12517     bool sax_parse(SAX* sax, const bool strict = true)
12518     {
12519         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
12520         const bool result = sax_parse_internal(sax);
12521 
12522         // strict mode: next byte must be EOF
12523         if (result && strict && (get_token() != token_type::end_of_input))
12524         {
12525             return sax->parse_error(m_lexer.get_position(),
12526                                     m_lexer.get_token_string(),
12527                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12528         }
12529 
12530         return result;
12531     }
12532 
12533   private:
12534     template<typename SAX>
12535     JSON_HEDLEY_NON_NULL(2)
12536     bool sax_parse_internal(SAX* sax)
12537     {
12538         // stack to remember the hierarchy of structured values we are parsing
12539         // true = array; false = object
12540         std::vector<bool> states;
12541         // value to avoid a goto (see comment where set to true)
12542         bool skip_to_state_evaluation = false;
12543 
12544         while (true)
12545         {
12546             if (!skip_to_state_evaluation)
12547             {
12548                 // invariant: get_token() was called before each iteration
12549                 switch (last_token)
12550                 {
12551                     case token_type::begin_object:
12552                     {
12553                         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12554                         {
12555                             return false;
12556                         }
12557 
12558                         // closing } -> we are done
12559                         if (get_token() == token_type::end_object)
12560                         {
12561                             if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12562                             {
12563                                 return false;
12564                             }
12565                             break;
12566                         }
12567 
12568                         // parse key
12569                         if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12570                         {
12571                             return sax->parse_error(m_lexer.get_position(),
12572                                                     m_lexer.get_token_string(),
12573                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12574                         }
12575                         if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12576                         {
12577                             return false;
12578                         }
12579 
12580                         // parse separator (:)
12581                         if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12582                         {
12583                             return sax->parse_error(m_lexer.get_position(),
12584                                                     m_lexer.get_token_string(),
12585                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12586                         }
12587 
12588                         // remember we are now inside an object
12589                         states.push_back(false);
12590 
12591                         // parse values
12592                         get_token();
12593                         continue;
12594                     }
12595 
12596                     case token_type::begin_array:
12597                     {
12598                         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12599                         {
12600                             return false;
12601                         }
12602 
12603                         // closing ] -> we are done
12604                         if (get_token() == token_type::end_array)
12605                         {
12606                             if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12607                             {
12608                                 return false;
12609                             }
12610                             break;
12611                         }
12612 
12613                         // remember we are now inside an array
12614                         states.push_back(true);
12615 
12616                         // parse values (no need to call get_token)
12617                         continue;
12618                     }
12619 
12620                     case token_type::value_float:
12621                     {
12622                         const auto res = m_lexer.get_number_float();
12623 
12624                         if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12625                         {
12626                             return sax->parse_error(m_lexer.get_position(),
12627                                                     m_lexer.get_token_string(),
12628                                                     out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12629                         }
12630 
12631                         if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12632                         {
12633                             return false;
12634                         }
12635 
12636                         break;
12637                     }
12638 
12639                     case token_type::literal_false:
12640                     {
12641                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12642                         {
12643                             return false;
12644                         }
12645                         break;
12646                     }
12647 
12648                     case token_type::literal_null:
12649                     {
12650                         if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12651                         {
12652                             return false;
12653                         }
12654                         break;
12655                     }
12656 
12657                     case token_type::literal_true:
12658                     {
12659                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12660                         {
12661                             return false;
12662                         }
12663                         break;
12664                     }
12665 
12666                     case token_type::value_integer:
12667                     {
12668                         if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12669                         {
12670                             return false;
12671                         }
12672                         break;
12673                     }
12674 
12675                     case token_type::value_string:
12676                     {
12677                         if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12678                         {
12679                             return false;
12680                         }
12681                         break;
12682                     }
12683 
12684                     case token_type::value_unsigned:
12685                     {
12686                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12687                         {
12688                             return false;
12689                         }
12690                         break;
12691                     }
12692 
12693                     case token_type::parse_error:
12694                     {
12695                         // using "uninitialized" to avoid "expected" message
12696                         return sax->parse_error(m_lexer.get_position(),
12697                                                 m_lexer.get_token_string(),
12698                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12699                     }
12700                     case token_type::end_of_input:
12701                     {
12702                         if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
12703                         {
12704                             return sax->parse_error(m_lexer.get_position(),
12705                                                     m_lexer.get_token_string(),
12706                                                     parse_error::create(101, m_lexer.get_position(),
12707                                                             "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12708                         }
12709 
12710                         return sax->parse_error(m_lexer.get_position(),
12711                                                 m_lexer.get_token_string(),
12712                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12713                     }
12714                     case token_type::uninitialized:
12715                     case token_type::end_array:
12716                     case token_type::end_object:
12717                     case token_type::name_separator:
12718                     case token_type::value_separator:
12719                     case token_type::literal_or_value:
12720                     default: // the last token was unexpected
12721                     {
12722                         return sax->parse_error(m_lexer.get_position(),
12723                                                 m_lexer.get_token_string(),
12724                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12725                     }
12726                 }
12727             }
12728             else
12729             {
12730                 skip_to_state_evaluation = false;
12731             }
12732 
12733             // we reached this line after we successfully parsed a value
12734             if (states.empty())
12735             {
12736                 // empty stack: we reached the end of the hierarchy: done
12737                 return true;
12738             }
12739 
12740             if (states.back())  // array
12741             {
12742                 // comma -> next value
12743                 if (get_token() == token_type::value_separator)
12744                 {
12745                     // parse a new value
12746                     get_token();
12747                     continue;
12748                 }
12749 
12750                 // closing ]
12751                 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12752                 {
12753                     if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12754                     {
12755                         return false;
12756                     }
12757 
12758                     // We are done with this array. Before we can parse a
12759                     // new value, we need to evaluate the new state first.
12760                     // By setting skip_to_state_evaluation to false, we
12761                     // are effectively jumping to the beginning of this if.
12762                     JSON_ASSERT(!states.empty());
12763                     states.pop_back();
12764                     skip_to_state_evaluation = true;
12765                     continue;
12766                 }
12767 
12768                 return sax->parse_error(m_lexer.get_position(),
12769                                         m_lexer.get_token_string(),
12770                                         parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12771             }
12772 
12773             // states.back() is false -> object
12774 
12775             // comma -> next value
12776             if (get_token() == token_type::value_separator)
12777             {
12778                 // parse key
12779                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12780                 {
12781                     return sax->parse_error(m_lexer.get_position(),
12782                                             m_lexer.get_token_string(),
12783                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12784                 }
12785 
12786                 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12787                 {
12788                     return false;
12789                 }
12790 
12791                 // parse separator (:)
12792                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12793                 {
12794                     return sax->parse_error(m_lexer.get_position(),
12795                                             m_lexer.get_token_string(),
12796                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12797                 }
12798 
12799                 // parse values
12800                 get_token();
12801                 continue;
12802             }
12803 
12804             // closing }
12805             if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12806             {
12807                 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12808                 {
12809                     return false;
12810                 }
12811 
12812                 // We are done with this object. Before we can parse a
12813                 // new value, we need to evaluate the new state first.
12814                 // By setting skip_to_state_evaluation to false, we
12815                 // are effectively jumping to the beginning of this if.
12816                 JSON_ASSERT(!states.empty());
12817                 states.pop_back();
12818                 skip_to_state_evaluation = true;
12819                 continue;
12820             }
12821 
12822             return sax->parse_error(m_lexer.get_position(),
12823                                     m_lexer.get_token_string(),
12824                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12825         }
12826     }
12827 
12828     /// get next token from lexer
12829     token_type get_token()
12830     {
12831         return last_token = m_lexer.scan();
12832     }
12833 
12834     std::string exception_message(const token_type expected, const std::string& context)
12835     {
12836         std::string error_msg = "syntax error ";
12837 
12838         if (!context.empty())
12839         {
12840             error_msg += concat("while parsing ", context, ' ');
12841         }
12842 
12843         error_msg += "- ";
12844 
12845         if (last_token == token_type::parse_error)
12846         {
12847             error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12848                                 m_lexer.get_token_string(), '\'');
12849         }
12850         else
12851         {
12852             error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12853         }
12854 
12855         if (expected != token_type::uninitialized)
12856         {
12857             error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12858         }
12859 
12860         return error_msg;
12861     }
12862 
12863   private:
12864     /// callback function
12865     const parser_callback_t<BasicJsonType> callback = nullptr;
12866     /// the type of the last read token
12867     token_type last_token = token_type::uninitialized;
12868     /// the lexer
12869     lexer_t m_lexer;
12870     /// whether to throw exceptions in case of errors
12871     const bool allow_exceptions = true;
12872 };
12873 
12874 }  // namespace detail
12875 NLOHMANN_JSON_NAMESPACE_END
12876 
12877 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
12878 //     __ _____ _____ _____
12879 //  __|  |   __|     |   | |  JSON for Modern C++
12880 // |  |  |__   |  |  | | | |  version 3.11.3
12881 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
12882 //
12883 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
12884 // SPDX-License-Identifier: MIT
12885 
12886 
12887 
12888 // #include <nlohmann/detail/abi_macros.hpp>
12889 
12890 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12891 //     __ _____ _____ _____
12892 //  __|  |   __|     |   | |  JSON for Modern C++
12893 // |  |  |__   |  |  | | | |  version 3.11.3
12894 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
12895 //
12896 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
12897 // SPDX-License-Identifier: MIT
12898 
12899 
12900 
12901 #include <cstddef> // ptrdiff_t
12902 #include <limits>  // numeric_limits
12903 
12904 // #include <nlohmann/detail/macro_scope.hpp>
12905 
12906 
12907 NLOHMANN_JSON_NAMESPACE_BEGIN
12908 namespace detail
12909 {
12910 
12911 /* 
12912 @brief an iterator for primitive JSON types 
12913  
12914 This class models an iterator for primitive JSON types (boolean, number, 
12915 string). It's only purpose is to allow the iterator/const_iterator classes 
12916 to "iterate" over primitive values. Internally, the iterator is modeled by 
12917 a `difference_type` variable. Value begin_value (`0`) models the begin, 
12918 end_value (`1`) models past the end. 
12919 */
12920 class primitive_iterator_t
12921 {
12922   private:
12923     using difference_type = std::ptrdiff_t;
12924     static constexpr difference_type begin_value = 0;
12925     static constexpr difference_type end_value = begin_value + 1;
12926 
12927   JSON_PRIVATE_UNLESS_TESTED:
12928     /// iterator as signed integer type
12929     difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12930 
12931   public:
12932     constexpr difference_type get_value() const noexcept
12933     {
12934         return m_it;
12935     }
12936 
12937     /// set iterator to a defined beginning
12938     void set_begin() noexcept
12939     {
12940         m_it = begin_value;
12941     }
12942 
12943     /// set iterator to a defined past the end
12944     void set_end() noexcept
12945     {
12946         m_it = end_value;
12947     }
12948 
12949     /// return whether the iterator can be dereferenced
12950     constexpr bool is_begin() const noexcept
12951     {
12952         return m_it == begin_value;
12953     }
12954 
12955     /// return whether the iterator is at end
12956     constexpr bool is_end() const noexcept
12957     {
12958         return m_it == end_value;
12959     }
12960 
12961     friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12962     {
12963         return lhs.m_it == rhs.m_it;
12964     }
12965 
12966     friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12967     {
12968         return lhs.m_it < rhs.m_it;
12969     }
12970 
12971     primitive_iterator_t operator+(difference_type n) noexcept
12972     {
12973         auto result = *this;
12974         result += n;
12975         return result;
12976     }
12977 
12978     friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12979     {
12980         return lhs.m_it - rhs.m_it;
12981     }
12982 
12983     primitive_iterator_t& operator++() noexcept
12984     {
12985         ++m_it;
12986         return *this;
12987     }
12988 
12989     primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12990     {
12991         auto result = *this;
12992         ++m_it;
12993         return result;
12994     }
12995 
12996     primitive_iterator_t& operator--() noexcept
12997     {
12998         --m_it;
12999         return *this;
13000     }
13001 
13002     primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13003     {
13004         auto result = *this;
13005         --m_it;
13006         return result;
13007     }
13008 
13009     primitive_iterator_t& operator+=(difference_type n) noexcept
13010     {
13011         m_it += n;
13012         return *this;
13013     }
13014 
13015     primitive_iterator_t& operator-=(difference_type n) noexcept
13016     {
13017         m_it -= n;
13018         return *this;
13019     }
13020 };
13021 
13022 }  // namespace detail
13023 NLOHMANN_JSON_NAMESPACE_END
13024 
13025 
13026 NLOHMANN_JSON_NAMESPACE_BEGIN
13027 namespace detail
13028 {
13029 
13030 /*! 
13031 @brief an iterator value 
13032  
13033 @note This structure could easily be a union, but MSVC currently does not allow 
13034 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. 
13035 */
13036 template<typename BasicJsonType> struct internal_iterator
13037 {
13038     /// iterator for JSON objects
13039     typename BasicJsonType::object_t::iterator object_iterator {};
13040     /// iterator for JSON arrays
13041     typename BasicJsonType::array_t::iterator array_iterator {};
13042     /// generic iterator for all other types
13043     primitive_iterator_t primitive_iterator {};
13044 };
13045 
13046 }  // namespace detail
13047 NLOHMANN_JSON_NAMESPACE_END
13048 
13049 // #include <nlohmann/detail/iterators/iter_impl.hpp>
13050 //     __ _____ _____ _____
13051 //  __|  |   __|     |   | |  JSON for Modern C++
13052 // |  |  |__   |  |  | | | |  version 3.11.3
13053 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13054 //
13055 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
13056 // SPDX-License-Identifier: MIT
13057 
13058 
13059 
13060 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13061 #include <type_traits> // conditional, is_const, remove_const
13062 
13063 // #include <nlohmann/detail/exceptions.hpp>
13064 
13065 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
13066 
13067 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13068 
13069 // #include <nlohmann/detail/macro_scope.hpp>
13070 
13071 // #include <nlohmann/detail/meta/cpp_future.hpp>
13072 
13073 // #include <nlohmann/detail/meta/type_traits.hpp>
13074 
13075 // #include <nlohmann/detail/value_t.hpp>
13076 
13077 
13078 NLOHMANN_JSON_NAMESPACE_BEGIN
13079 namespace detail
13080 {
13081 
13082 // forward declare, to be able to friend it later on
13083 template<typename IteratorType> class iteration_proxy;
13084 template<typename IteratorType> class iteration_proxy_value;
13085 
13086 /*! 
13087 @brief a template for a bidirectional iterator for the @ref basic_json class 
13088 This class implements a both iterators (iterator and const_iterator) for the 
13089 @ref basic_json class. 
13090 @note An iterator is called *initialized* when a pointer to a JSON value has 
13091       been set (e.g., by a constructor or a copy assignment). If the iterator is 
13092       default-constructed, it is *uninitialized* and most methods are undefined. 
13093       **The library uses assertions to detect calls on uninitialized iterators.** 
13094 @requirement The class satisfies the following concept requirements: 
13095 - 
13096 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 
13097   The iterator that can be moved can be moved in both directions (i.e. 
13098   incremented and decremented). 
13099 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional 
13100        iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) 
13101 */
13102 template<typename BasicJsonType>
13103 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13104 {
13105     /// the iterator with BasicJsonType of different const-ness
13106     using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13107     /// allow basic_json to access private members
13108     friend other_iter_impl;
13109     friend BasicJsonType;
13110     friend iteration_proxy<iter_impl>;
13111     friend iteration_proxy_value<iter_impl>;
13112 
13113     using object_t = typename BasicJsonType::object_t;
13114     using array_t = typename BasicJsonType::array_t;
13115     // make sure BasicJsonType is basic_json or const basic_json
13116     static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
13117                   "iter_impl only accepts (const) basic_json");
13118     // superficial check for the LegacyBidirectionalIterator named requirement
13119     static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13120                   &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13121                   "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13122 
13123   public:
13124     /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
13125     /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
13126     /// A user-defined iterator should provide publicly accessible typedefs named
13127     /// iterator_category, value_type, difference_type, pointer, and reference.
13128     /// Note that value_type is required to be non-const, even for constant iterators.
13129     using iterator_category = std::bidirectional_iterator_tag;
13130 
13131     /// the type of the values when the iterator is dereferenced
13132     using value_type = typename BasicJsonType::value_type;
13133     /// a type to represent differences between iterators
13134     using difference_type = typename BasicJsonType::difference_type;
13135     /// defines a pointer to the type iterated over (value_type)
13136     using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13137           typename BasicJsonType::const_pointer,
13138           typename BasicJsonType::pointer>::type;
13139     /// defines a reference to the type iterated over (value_type)
13140     using reference =
13141         typename std::conditional<std::is_const<BasicJsonType>::value,
13142         typename BasicJsonType::const_reference,
13143         typename BasicJsonType::reference>::type;
13144 
13145     iter_impl() = default;
13146     ~iter_impl() = default;
13147     iter_impl(iter_impl&&) noexcept = default;
13148     iter_impl& operator=(iter_impl&&) noexcept = default;
13149 
13150     /*! 
13151     @brief constructor for a given JSON instance 
13152     @param[in] object  pointer to a JSON object for this iterator 
13153     @pre object != nullptr 
13154     @post The iterator is initialized; i.e. `m_object != nullptr`. 
13155     */
13156     explicit iter_impl(pointer object) noexcept : m_object(object)
13157     {
13158         JSON_ASSERT(m_object != nullptr);
13159 
13160         switch (m_object->m_data.m_type)
13161         {
13162             case value_t::object:
13163             {
13164                 m_it.object_iterator = typename object_t::iterator();
13165                 break;
13166             }
13167 
13168             case value_t::array:
13169             {
13170                 m_it.array_iterator = typename array_t::iterator();
13171                 break;
13172             }
13173 
13174             case value_t::null:
13175             case value_t::string:
13176             case value_t::boolean:
13177             case value_t::number_integer:
13178             case value_t::number_unsigned:
13179             case value_t::number_float:
13180             case value_t::binary:
13181             case value_t::discarded:
13182             default:
13183             {
13184                 m_it.primitive_iterator = primitive_iterator_t();
13185                 break;
13186             }
13187         }
13188     }
13189 
13190     /*! 
13191     @note The conventional copy constructor and copy assignment are implicitly 
13192           defined. Combined with the following converting constructor and 
13193           assignment, they support: (1) copy from iterator to iterator, (2) 
13194           copy from const iterator to const iterator, and (3) conversion from 
13195           iterator to const iterator. However conversion from const iterator 
13196           to iterator is not defined. 
13197     */
13198 
13199     /*! 
13200     @brief const copy constructor 
13201     @param[in] other const iterator to copy from 
13202     @note This copy constructor had to be defined explicitly to circumvent a bug 
13203           occurring on msvc v19.0 compiler (VS 2015) debug build. For more 
13204           information refer to: https://github.com/nlohmann/json/issues/1608 
13205     */
13206     iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
13207         : m_object(other.m_object), m_it(other.m_it)
13208     {}
13209 
13210     /*! 
13211     @brief converting assignment 
13212     @param[in] other const iterator to copy from 
13213     @return const/non-const iterator 
13214     @note It is not checked whether @a other is initialized. 
13215     */
13216     iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
13217     {
13218         if (&other != this)
13219         {
13220             m_object = other.m_object;
13221             m_it = other.m_it;
13222         }
13223         return *this;
13224     }
13225 
13226     /*! 
13227     @brief converting constructor 
13228     @param[in] other  non-const iterator to copy from 
13229     @note It is not checked whether @a other is initialized. 
13230     */
13231     iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13232         : m_object(other.m_object), m_it(other.m_it)
13233     {}
13234 
13235     /*! 
13236     @brief converting assignment 
13237     @param[in] other  non-const iterator to copy from 
13238     @return const/non-const iterator 
13239     @note It is not checked whether @a other is initialized. 
13240     */
13241     iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13242     {
13243         m_object = other.m_object;
13244         m_it = other.m_it;
13245         return *this;
13246     }
13247 
13248   JSON_PRIVATE_UNLESS_TESTED:
13249     /*! 
13250     @brief set the iterator to the first value 
13251     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13252     */
13253     void set_begin() noexcept
13254     {
13255         JSON_ASSERT(m_object != nullptr);
13256 
13257         switch (m_object->m_data.m_type)
13258         {
13259             case value_t::object:
13260             {
13261                 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13262                 break;
13263             }
13264 
13265             case value_t::array:
13266             {
13267                 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13268                 break;
13269             }
13270 
13271             case value_t::null:
13272             {
13273                 // set to end so begin()==end() is true: null is empty
13274                 m_it.primitive_iterator.set_end();
13275                 break;
13276             }
13277 
13278             case value_t::string:
13279             case value_t::boolean:
13280             case value_t::number_integer:
13281             case value_t::number_unsigned:
13282             case value_t::number_float:
13283             case value_t::binary:
13284             case value_t::discarded:
13285             default:
13286             {
13287                 m_it.primitive_iterator.set_begin();
13288                 break;
13289             }
13290         }
13291     }
13292 
13293     /*! 
13294     @brief set the iterator past the last value 
13295     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13296     */
13297     void set_end() noexcept
13298     {
13299         JSON_ASSERT(m_object != nullptr);
13300 
13301         switch (m_object->m_data.m_type)
13302         {
13303             case value_t::object:
13304             {
13305                 m_it.object_iterator = m_object->m_data.m_value.object->end();
13306                 break;
13307             }
13308 
13309             case value_t::array:
13310             {
13311                 m_it.array_iterator = m_object->m_data.m_value.array->end();
13312                 break;
13313             }
13314 
13315             case value_t::null:
13316             case value_t::string:
13317             case value_t::boolean:
13318             case value_t::number_integer:
13319             case value_t::number_unsigned:
13320             case value_t::number_float:
13321             case value_t::binary:
13322             case value_t::discarded:
13323             default:
13324             {
13325                 m_it.primitive_iterator.set_end();
13326                 break;
13327             }
13328         }
13329     }
13330 
13331   public:
13332     /*! 
13333     @brief return a reference to the value pointed to by the iterator 
13334     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13335     */
13336     reference operator*() const
13337     {
13338         JSON_ASSERT(m_object != nullptr);
13339 
13340         switch (m_object->m_data.m_type)
13341         {
13342             case value_t::object:
13343             {
13344                 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13345                 return m_it.object_iterator->second;
13346             }
13347 
13348             case value_t::array:
13349             {
13350                 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13351                 return *m_it.array_iterator;
13352             }
13353 
13354             case value_t::null:
13355                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13356 
13357             case value_t::string:
13358             case value_t::boolean:
13359             case value_t::number_integer:
13360             case value_t::number_unsigned:
13361             case value_t::number_float:
13362             case value_t::binary:
13363             case value_t::discarded:
13364             default:
13365             {
13366                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13367                 {
13368                     return *m_object;
13369                 }
13370 
13371                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13372             }
13373         }
13374     }
13375 
13376     /*! 
13377     @brief dereference the iterator 
13378     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13379     */
13380     pointer operator->() const
13381     {
13382         JSON_ASSERT(m_object != nullptr);
13383 
13384         switch (m_object->m_data.m_type)
13385         {
13386             case value_t::object:
13387             {
13388                 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13389                 return &(m_it.object_iterator->second);
13390             }
13391 
13392             case value_t::array:
13393             {
13394                 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13395                 return &*m_it.array_iterator;
13396             }
13397 
13398             case value_t::null:
13399             case value_t::string:
13400             case value_t::boolean:
13401             case value_t::number_integer:
13402             case value_t::number_unsigned:
13403             case value_t::number_float:
13404             case value_t::binary:
13405             case value_t::discarded:
13406             default:
13407             {
13408                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13409                 {
13410                     return m_object;
13411                 }
13412 
13413                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13414             }
13415         }
13416     }
13417 
13418     /*! 
13419     @brief post-increment (it++) 
13420     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13421     */
13422     iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13423     {
13424         auto result = *this;
13425         ++(*this);
13426         return result;
13427     }
13428 
13429     /*! 
13430     @brief pre-increment (++it) 
13431     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13432     */
13433     iter_impl& operator++()
13434     {
13435         JSON_ASSERT(m_object != nullptr);
13436 
13437         switch (m_object->m_data.m_type)
13438         {
13439             case value_t::object:
13440             {
13441                 std::advance(m_it.object_iterator, 1);
13442                 break;
13443             }
13444 
13445             case value_t::array:
13446             {
13447                 std::advance(m_it.array_iterator, 1);
13448                 break;
13449             }
13450 
13451             case value_t::null:
13452             case value_t::string:
13453             case value_t::boolean:
13454             case value_t::number_integer:
13455             case value_t::number_unsigned:
13456             case value_t::number_float:
13457             case value_t::binary:
13458             case value_t::discarded:
13459             default:
13460             {
13461                 ++m_it.primitive_iterator;
13462                 break;
13463             }
13464         }
13465 
13466         return *this;
13467     }
13468 
13469     /*! 
13470     @brief post-decrement (it--) 
13471     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13472     */
13473     iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13474     {
13475         auto result = *this;
13476         --(*this);
13477         return result;
13478     }
13479 
13480     /*! 
13481     @brief pre-decrement (--it) 
13482     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13483     */
13484     iter_impl& operator--()
13485     {
13486         JSON_ASSERT(m_object != nullptr);
13487 
13488         switch (m_object->m_data.m_type)
13489         {
13490             case value_t::object:
13491             {
13492                 std::advance(m_it.object_iterator, -1);
13493                 break;
13494             }
13495 
13496             case value_t::array:
13497             {
13498                 std::advance(m_it.array_iterator, -1);
13499                 break;
13500             }
13501 
13502             case value_t::null:
13503             case value_t::string:
13504             case value_t::boolean:
13505             case value_t::number_integer:
13506             case value_t::number_unsigned:
13507             case value_t::number_float:
13508             case value_t::binary:
13509             case value_t::discarded:
13510             default:
13511             {
13512                 --m_it.primitive_iterator;
13513                 break;
13514             }
13515         }
13516 
13517         return *this;
13518     }
13519 
13520     /*! 
13521     @brief comparison: equal 
13522     @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 
13523     */
13524     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13525     bool operator==(const IterImpl& other) const
13526     {
13527         // if objects are not the same, the comparison is undefined
13528         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13529         {
13530             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13531         }
13532 
13533         // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
13534         if (m_object == nullptr)
13535         {
13536             return true;
13537         }
13538 
13539         switch (m_object->m_data.m_type)
13540         {
13541             case value_t::object:
13542                 return (m_it.object_iterator == other.m_it.object_iterator);
13543 
13544             case value_t::array:
13545                 return (m_it.array_iterator == other.m_it.array_iterator);
13546 
13547             case value_t::null:
13548             case value_t::string:
13549             case value_t::boolean:
13550             case value_t::number_integer:
13551             case value_t::number_unsigned:
13552             case value_t::number_float:
13553             case value_t::binary:
13554             case value_t::discarded:
13555             default:
13556                 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13557         }
13558     }
13559 
13560     /*! 
13561     @brief comparison: not equal 
13562     @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 
13563     */
13564     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13565     bool operator!=(const IterImpl& other) const
13566     {
13567         return !operator==(other);
13568     }
13569 
13570     /*! 
13571     @brief comparison: smaller 
13572     @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 
13573     */
13574     bool operator<(const iter_impl& other) const
13575     {
13576         // if objects are not the same, the comparison is undefined
13577         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13578         {
13579             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13580         }
13581 
13582         // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
13583         if (m_object == nullptr)
13584         {
13585             // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
13586             return false;
13587         }
13588 
13589         switch (m_object->m_data.m_type)
13590         {
13591             case value_t::object:
13592                 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13593 
13594             case value_t::array:
13595                 return (m_it.array_iterator < other.m_it.array_iterator);
13596 
13597             case value_t::null:
13598             case value_t::string:
13599             case value_t::boolean:
13600             case value_t::number_integer:
13601             case value_t::number_unsigned:
13602             case value_t::number_float:
13603             case value_t::binary:
13604             case value_t::discarded:
13605             default:
13606                 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13607         }
13608     }
13609 
13610     /*! 
13611     @brief comparison: less than or equal 
13612     @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 
13613     */
13614     bool operator<=(const iter_impl& other) const
13615     {
13616         return !other.operator < (*this);
13617     }
13618 
13619     /*! 
13620     @brief comparison: greater than 
13621     @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 
13622     */
13623     bool operator>(const iter_impl& other) const
13624     {
13625         return !operator<=(other);
13626     }
13627 
13628     /*! 
13629     @brief comparison: greater than or equal 
13630     @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized. 
13631     */
13632     bool operator>=(const iter_impl& other) const
13633     {
13634         return !operator<(other);
13635     }
13636 
13637     /*! 
13638     @brief add to iterator 
13639     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13640     */
13641     iter_impl& operator+=(difference_type i)
13642     {
13643         JSON_ASSERT(m_object != nullptr);
13644 
13645         switch (m_object->m_data.m_type)
13646         {
13647             case value_t::object:
13648                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13649 
13650             case value_t::array:
13651             {
13652                 std::advance(m_it.array_iterator, i);
13653                 break;
13654             }
13655 
13656             case value_t::null:
13657             case value_t::string:
13658             case value_t::boolean:
13659             case value_t::number_integer:
13660             case value_t::number_unsigned:
13661             case value_t::number_float:
13662             case value_t::binary:
13663             case value_t::discarded:
13664             default:
13665             {
13666                 m_it.primitive_iterator += i;
13667                 break;
13668             }
13669         }
13670 
13671         return *this;
13672     }
13673 
13674     /*! 
13675     @brief subtract from iterator 
13676     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13677     */
13678     iter_impl& operator-=(difference_type i)
13679     {
13680         return operator+=(-i);
13681     }
13682 
13683     /*! 
13684     @brief add to iterator 
13685     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13686     */
13687     iter_impl operator+(difference_type i) const
13688     {
13689         auto result = *this;
13690         result += i;
13691         return result;
13692     }
13693 
13694     /*! 
13695     @brief addition of distance and iterator 
13696     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13697     */
13698     friend iter_impl operator+(difference_type i, const iter_impl& it)
13699     {
13700         auto result = it;
13701         result += i;
13702         return result;
13703     }
13704 
13705     /*! 
13706     @brief subtract from iterator 
13707     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13708     */
13709     iter_impl operator-(difference_type i) const
13710     {
13711         auto result = *this;
13712         result -= i;
13713         return result;
13714     }
13715 
13716     /*! 
13717     @brief return difference 
13718     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13719     */
13720     difference_type operator-(const iter_impl& other) const
13721     {
13722         JSON_ASSERT(m_object != nullptr);
13723 
13724         switch (m_object->m_data.m_type)
13725         {
13726             case value_t::object:
13727                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13728 
13729             case value_t::array:
13730                 return m_it.array_iterator - other.m_it.array_iterator;
13731 
13732             case value_t::null:
13733             case value_t::string:
13734             case value_t::boolean:
13735             case value_t::number_integer:
13736             case value_t::number_unsigned:
13737             case value_t::number_float:
13738             case value_t::binary:
13739             case value_t::discarded:
13740             default:
13741                 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13742         }
13743     }
13744 
13745     /*! 
13746     @brief access to successor 
13747     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13748     */
13749     reference operator[](difference_type n) const
13750     {
13751         JSON_ASSERT(m_object != nullptr);
13752 
13753         switch (m_object->m_data.m_type)
13754         {
13755             case value_t::object:
13756                 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13757 
13758             case value_t::array:
13759                 return *std::next(m_it.array_iterator, n);
13760 
13761             case value_t::null:
13762                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13763 
13764             case value_t::string:
13765             case value_t::boolean:
13766             case value_t::number_integer:
13767             case value_t::number_unsigned:
13768             case value_t::number_float:
13769             case value_t::binary:
13770             case value_t::discarded:
13771             default:
13772             {
13773                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13774                 {
13775                     return *m_object;
13776                 }
13777 
13778                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13779             }
13780         }
13781     }
13782 
13783     /*! 
13784     @brief return the key of an object iterator 
13785     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13786     */
13787     const typename object_t::key_type& key() const
13788     {
13789         JSON_ASSERT(m_object != nullptr);
13790 
13791         if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13792         {
13793             return m_it.object_iterator->first;
13794         }
13795 
13796         JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13797     }
13798 
13799     /*! 
13800     @brief return the value of an iterator 
13801     @pre The iterator is initialized; i.e. `m_object != nullptr`. 
13802     */
13803     reference value() const
13804     {
13805         return operator*();
13806     }
13807 
13808   JSON_PRIVATE_UNLESS_TESTED:
13809     /// associated JSON instance
13810     pointer m_object = nullptr;
13811     /// the actual iterator of the associated instance
13812     internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
13813 };
13814 
13815 }  // namespace detail
13816 NLOHMANN_JSON_NAMESPACE_END
13817 
13818 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13819 
13820 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13821 //     __ _____ _____ _____
13822 //  __|  |   __|     |   | |  JSON for Modern C++
13823 // |  |  |__   |  |  | | | |  version 3.11.3
13824 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13825 //
13826 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
13827 // SPDX-License-Identifier: MIT
13828 
13829 
13830 
13831 #include <cstddef> // ptrdiff_t
13832 #include <iterator> // reverse_iterator
13833 #include <utility> // declval
13834 
13835 // #include <nlohmann/detail/abi_macros.hpp>
13836 
13837 
13838 NLOHMANN_JSON_NAMESPACE_BEGIN
13839 namespace detail
13840 {
13841 
13842 //////////////////////
13843 // reverse_iterator //
13844 //////////////////////
13845 
13846 /*! 
13847 @brief a template for a reverse iterator class 
13848  
13849 @tparam Base the base iterator type to reverse. Valid types are @ref 
13850 iterator (to create @ref reverse_iterator) and @ref const_iterator (to 
13851 create @ref const_reverse_iterator). 
13852  
13853 @requirement The class satisfies the following concept requirements: 
13854 - 
13855 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 
13856   The iterator that can be moved can be moved in both directions (i.e. 
13857   incremented and decremented). 
13858 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): 
13859   It is possible to write to the pointed-to element (only if @a Base is 
13860   @ref iterator). 
13861  
13862 @since version 1.0.0 
13863 */
13864 template<typename Base>
13865 class json_reverse_iterator : public std::reverse_iterator<Base>
13866 {
13867   public:
13868     using difference_type = std::ptrdiff_t;
13869     /// shortcut to the reverse iterator adapter
13870     using base_iterator = std::reverse_iterator<Base>;
13871     /// the reference type for the pointed-to element
13872     using reference = typename Base::reference;
13873 
13874     /// create reverse iterator from iterator
13875     explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13876         : base_iterator(it) {}
13877 
13878     /// create reverse iterator from base class
13879     explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13880 
13881     /// post-increment (it++)
13882     json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13883     {
13884         return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13885     }
13886 
13887     /// pre-increment (++it)
13888     json_reverse_iterator& operator++()
13889     {
13890         return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13891     }
13892 
13893     /// post-decrement (it--)
13894     json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13895     {
13896         return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13897     }
13898 
13899     /// pre-decrement (--it)
13900     json_reverse_iterator& operator--()
13901     {
13902         return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13903     }
13904 
13905     /// add to iterator
13906     json_reverse_iterator& operator+=(difference_type i)
13907     {
13908         return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13909     }
13910 
13911     /// add to iterator
13912     json_reverse_iterator operator+(difference_type i) const
13913     {
13914         return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13915     }
13916 
13917     /// subtract from iterator
13918     json_reverse_iterator operator-(difference_type i) const
13919     {
13920         return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13921     }
13922 
13923     /// return difference
13924     difference_type operator-(const json_reverse_iterator& other) const
13925     {
13926         return base_iterator(*this) - base_iterator(other);
13927     }
13928 
13929     /// access to successor
13930     reference operator[](difference_type n) const
13931     {
13932         return *(this->operator+(n));
13933     }
13934 
13935     /// return the key of an object iterator
13936     auto key() const -> decltype(std::declval<Base>().key())
13937     {
13938         auto it = --this->base();
13939         return it.key();
13940     }
13941 
13942     /// return the value of an iterator
13943     reference value() const
13944     {
13945         auto it = --this->base();
13946         return it.operator * ();
13947     }
13948 };
13949 
13950 }  // namespace detail
13951 NLOHMANN_JSON_NAMESPACE_END
13952 
13953 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13954 
13955 // #include <nlohmann/detail/json_custom_base_class.hpp>
13956 //     __ _____ _____ _____
13957 //  __|  |   __|     |   | |  JSON for Modern C++
13958 // |  |  |__   |  |  | | | |  version 3.11.3
13959 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13960 //
13961 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
13962 // SPDX-License-Identifier: MIT
13963 
13964 
13965 
13966 #include <type_traits> // conditional, is_same
13967 
13968 // #include <nlohmann/detail/abi_macros.hpp>
13969 
13970 
13971 NLOHMANN_JSON_NAMESPACE_BEGIN
13972 namespace detail
13973 {
13974 
13975 /*! 
13976 @brief Default base class of the @ref basic_json class. 
13977  
13978 So that the correct implementations of the copy / move ctors / assign operators 
13979 of @ref basic_json do not require complex case distinctions 
13980 (no base class / custom base class used as customization point), 
13981 @ref basic_json always has a base class. 
13982 By default, this class is used because it is empty and thus has no effect 
13983 on the behavior of @ref basic_json. 
13984 */
13985 struct json_default_base {};
13986 
13987 template<class T>
13988 using json_base_class = typename std::conditional <
13989                         std::is_same<T, void>::value,
13990                         json_default_base,
13991                         T
13992                         >::type;
13993 
13994 }  // namespace detail
13995 NLOHMANN_JSON_NAMESPACE_END
13996 
13997 // #include <nlohmann/detail/json_pointer.hpp>
13998 //     __ _____ _____ _____
13999 //  __|  |   __|     |   | |  JSON for Modern C++
14000 // |  |  |__   |  |  | | | |  version 3.11.3
14001 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14002 //
14003 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
14004 // SPDX-License-Identifier: MIT
14005 
14006 
14007 
14008 #include <algorithm> // all_of
14009 #include <cctype> // isdigit
14010 #include <cerrno> // errno, ERANGE
14011 #include <cstdlib> // strtoull
14012 #ifndef JSON_NO_IO
14013     #include <iosfwd> // ostream
14014 #endif  // JSON_NO_IO
14015 #include <limits> // max
14016 #include <numeric> // accumulate
14017 #include <string> // string
14018 #include <utility> // move
14019 #include <vector> // vector
14020 
14021 // #include <nlohmann/detail/exceptions.hpp>
14022 
14023 // #include <nlohmann/detail/macro_scope.hpp>
14024 
14025 // #include <nlohmann/detail/string_concat.hpp>
14026 
14027 // #include <nlohmann/detail/string_escape.hpp>
14028 
14029 // #include <nlohmann/detail/value_t.hpp>
14030 
14031 
14032 NLOHMANN_JSON_NAMESPACE_BEGIN
14033 
14034 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
14035 /// @sa https://json.nlohmann.me/api/json_pointer/
14036 template<typename RefStringType>
14037 class json_pointer
14038 {
14039     // allow basic_json to access private members
14040     NLOHMANN_BASIC_JSON_TPL_DECLARATION
14041     friend class basic_json;
14042 
14043     template<typename>
14044     friend class json_pointer;
14045 
14046     template<typename T>
14047     struct string_t_helper
14048     {
14049         using type = T;
14050     };
14051 
14052     NLOHMANN_BASIC_JSON_TPL_DECLARATION
14053     struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14054     {
14055         using type = StringType;
14056     };
14057 
14058   public:
14059     // for backwards compatibility accept BasicJsonType
14060     using string_t = typename string_t_helper<RefStringType>::type;
14061 
14062     /// @brief create JSON pointer
14063     /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
14064     explicit json_pointer(const string_t& s = "")
14065         : reference_tokens(split(s))
14066     {}
14067 
14068     /// @brief return a string representation of the JSON pointer
14069     /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
14070     string_t to_string() const
14071     {
14072         return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14073                                string_t{},
14074                                [](const string_t& a, const string_t& b)
14075         {
14076             return detail::concat(a, '/', detail::escape(b));
14077         });
14078     }
14079 
14080     /// @brief return a string representation of the JSON pointer
14081     /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
14082     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
14083     operator string_t() const
14084     {
14085         return to_string();
14086     }
14087 
14088 #ifndef JSON_NO_IO
14089     /// @brief write string representation of the JSON pointer to stream
14090     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
14091     friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14092     {
14093         o << ptr.to_string();
14094         return o;
14095     }
14096 #endif
14097 
14098     /// @brief append another JSON pointer at the end of this JSON pointer
14099     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14100     json_pointer& operator/=(const json_pointer& ptr)
14101     {
14102         reference_tokens.insert(reference_tokens.end(),
14103                                 ptr.reference_tokens.begin(),
14104                                 ptr.reference_tokens.end());
14105         return *this;
14106     }
14107 
14108     /// @brief append an unescaped reference token at the end of this JSON pointer
14109     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14110     json_pointer& operator/=(string_t token)
14111     {
14112         push_back(std::move(token));
14113         return *this;
14114     }
14115 
14116     /// @brief append an array index at the end of this JSON pointer
14117     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14118     json_pointer& operator/=(std::size_t array_idx)
14119     {
14120         return *this /= std::to_string(array_idx);
14121     }
14122 
14123     /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
14124     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14125     friend json_pointer operator/(const json_pointer& lhs,
14126                                   const json_pointer& rhs)
14127     {
14128         return json_pointer(lhs) /= rhs;
14129     }
14130 
14131     /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
14132     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14133     friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14134     {
14135         return json_pointer(lhs) /= std::move(token);
14136     }
14137 
14138     /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
14139     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14140     friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14141     {
14142         return json_pointer(lhs) /= array_idx;
14143     }
14144 
14145     /// @brief returns the parent of this JSON pointer
14146     /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
14147     json_pointer parent_pointer() const
14148     {
14149         if (empty())
14150         {
14151             return *this;
14152         }
14153 
14154         json_pointer res = *this;
14155         res.pop_back();
14156         return res;
14157     }
14158 
14159     /// @brief remove last reference token
14160     /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
14161     void pop_back()
14162     {
14163         if (JSON_HEDLEY_UNLIKELY(empty()))
14164         {
14165             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14166         }
14167 
14168         reference_tokens.pop_back();
14169     }
14170 
14171     /// @brief return last reference token
14172     /// @sa https://json.nlohmann.me/api/json_pointer/back/
14173     const string_t& back() const
14174     {
14175         if (JSON_HEDLEY_UNLIKELY(empty()))
14176         {
14177             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14178         }
14179 
14180         return reference_tokens.back();
14181     }
14182 
14183     /// @brief append an unescaped token at the end of the reference pointer
14184     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14185     void push_back(const string_t& token)
14186     {
14187         reference_tokens.push_back(token);
14188     }
14189 
14190     /// @brief append an unescaped token at the end of the reference pointer
14191     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14192     void push_back(string_t&& token)
14193     {
14194         reference_tokens.push_back(std::move(token));
14195     }
14196 
14197     /// @brief return whether pointer points to the root document
14198     /// @sa https://json.nlohmann.me/api/json_pointer/empty/
14199     bool empty() const noexcept
14200     {
14201         return reference_tokens.empty();
14202     }
14203 
14204   private:
14205     /*! 
14206     @param[in] s  reference token to be converted into an array index 
14207  
14208     @return integer representation of @a s 
14209  
14210     @throw parse_error.106  if an array index begins with '0' 
14211     @throw parse_error.109  if an array index begins not with a digit 
14212     @throw out_of_range.404 if string @a s could not be converted to an integer 
14213     @throw out_of_range.410 if an array index exceeds size_type 
14214     */
14215     template<typename BasicJsonType>
14216     static typename BasicJsonType::size_type array_index(const string_t& s)
14217     {
14218         using size_type = typename BasicJsonType::size_type;
14219 
14220         // error condition (cf. RFC 6901, Sect. 4)
14221         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14222         {
14223             JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14224         }
14225 
14226         // error condition (cf. RFC 6901, Sect. 4)
14227         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14228         {
14229             JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14230         }
14231 
14232         const char* p = s.c_str();
14233         char* p_end = nullptr;
14234         errno = 0; // strtoull doesn't reset errno
14235         const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14236         if (p == p_end // invalid input or empty string
14237                 || errno == ERANGE // out of range
14238                 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14239         {
14240             JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14241         }
14242 
14243         // only triggered on special platforms (like 32bit), see also
14244         // https://github.com/nlohmann/json/pull/2203
14245         if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
14246         {
14247             JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE
14248         }
14249 
14250         return static_cast<size_type>(res);
14251     }
14252 
14253   JSON_PRIVATE_UNLESS_TESTED:
14254     json_pointer top() const
14255     {
14256         if (JSON_HEDLEY_UNLIKELY(empty()))
14257         {
14258             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14259         }
14260 
14261         json_pointer result = *this;
14262         result.reference_tokens = {reference_tokens[0]};
14263         return result;
14264     }
14265 
14266   private:
14267     /*! 
14268     @brief create and return a reference to the pointed to value 
14269  
14270     @complexity Linear in the number of reference tokens. 
14271  
14272     @throw parse_error.109 if array index is not a number 
14273     @throw type_error.313 if value cannot be unflattened 
14274     */
14275     template<typename BasicJsonType>
14276     BasicJsonType& get_and_create(BasicJsonType& j) const
14277     {
14278         auto* result = &j;
14279 
14280         // in case no reference tokens exist, return a reference to the JSON value
14281         // j which will be overwritten by a primitive value
14282         for (const auto& reference_token : reference_tokens)
14283         {
14284             switch (result->type())
14285             {
14286                 case detail::value_t::null:
14287                 {
14288                     if (reference_token == "0")
14289                     {
14290                         // start a new array if reference token is 0
14291                         result = &result->operator[](0);
14292                     }
14293                     else
14294                     {
14295                         // start a new object otherwise
14296                         result = &result->operator[](reference_token);
14297                     }
14298                     break;
14299                 }
14300 
14301                 case detail::value_t::object:
14302                 {
14303                     // create an entry in the object
14304                     result = &result->operator[](reference_token);
14305                     break;
14306                 }
14307 
14308                 case detail::value_t::array:
14309                 {
14310                     // create an entry in the array
14311                     result = &result->operator[](array_index<BasicJsonType>(reference_token));
14312                     break;
14313                 }
14314 
14315                 /* 
14316                 The following code is only reached if there exists a reference 
14317                 token _and_ the current value is primitive. In this case, we have 
14318                 an error situation, because primitive values may only occur as 
14319                 single value; that is, with an empty list of reference tokens. 
14320                 */
14321                 case detail::value_t::string:
14322                 case detail::value_t::boolean:
14323                 case detail::value_t::number_integer:
14324                 case detail::value_t::number_unsigned:
14325                 case detail::value_t::number_float:
14326                 case detail::value_t::binary:
14327                 case detail::value_t::discarded:
14328                 default:
14329                     JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14330             }
14331         }
14332 
14333         return *result;
14334     }
14335 
14336     /*! 
14337     @brief return a reference to the pointed to value 
14338  
14339     @note This version does not throw if a value is not present, but tries to 
14340           create nested values instead. For instance, calling this function 
14341           with pointer `"/this/that"` on a null value is equivalent to calling 
14342           `operator[]("this").operator[]("that")` on that value, effectively 
14343           changing the null value to an object. 
14344  
14345     @param[in] ptr  a JSON value 
14346  
14347     @return reference to the JSON value pointed to by the JSON pointer 
14348  
14349     @complexity Linear in the length of the JSON pointer. 
14350  
14351     @throw parse_error.106   if an array index begins with '0' 
14352     @throw parse_error.109   if an array index was not a number 
14353     @throw out_of_range.404  if the JSON pointer can not be resolved 
14354     */
14355     template<typename BasicJsonType>
14356     BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14357     {
14358         for (const auto& reference_token : reference_tokens)
14359         {
14360             // convert null values to arrays or objects before continuing
14361             if (ptr->is_null())
14362             {
14363                 // check if reference token is a number
14364                 const bool nums =
14365                     std::all_of(reference_token.begin(), reference_token.end(),
14366                                 [](const unsigned char x)
14367                 {
14368                     return std::isdigit(x);
14369                 });
14370 
14371                 // change value to array for numbers or "-" or to object otherwise
14372                 *ptr = (nums || reference_token == "-")
14373                        ? detail::value_t::array
14374                        : detail::value_t::object;
14375             }
14376 
14377             switch (ptr->type())
14378             {
14379                 case detail::value_t::object:
14380                 {
14381                     // use unchecked object access
14382                     ptr = &ptr->operator[](reference_token);
14383                     break;
14384                 }
14385 
14386                 case detail::value_t::array:
14387                 {
14388                     if (reference_token == "-")
14389                     {
14390                         // explicitly treat "-" as index beyond the end
14391                         ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14392                     }
14393                     else
14394                     {
14395                         // convert array index to number; unchecked access
14396                         ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14397                     }
14398                     break;
14399                 }
14400 
14401                 case detail::value_t::null:
14402                 case detail::value_t::string:
14403                 case detail::value_t::boolean:
14404                 case detail::value_t::number_integer:
14405                 case detail::value_t::number_unsigned:
14406                 case detail::value_t::number_float:
14407                 case detail::value_t::binary:
14408                 case detail::value_t::discarded:
14409                 default:
14410                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14411             }
14412         }
14413 
14414         return *ptr;
14415     }
14416 
14417     /*! 
14418     @throw parse_error.106   if an array index begins with '0' 
14419     @throw parse_error.109   if an array index was not a number 
14420     @throw out_of_range.402  if the array index '-' is used 
14421     @throw out_of_range.404  if the JSON pointer can not be resolved 
14422     */
14423     template<typename BasicJsonType>
14424     BasicJsonType& get_checked(BasicJsonType* ptr) const
14425     {
14426         for (const auto& reference_token : reference_tokens)
14427         {
14428             switch (ptr->type())
14429             {
14430                 case detail::value_t::object:
14431                 {
14432                     // note: at performs range check
14433                     ptr = &ptr->at(reference_token);
14434                     break;
14435                 }
14436 
14437                 case detail::value_t::array:
14438                 {
14439                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14440                     {
14441                         // "-" always fails the range check
14442                         JSON_THROW(detail::out_of_range::create(402, detail::concat(
14443                                 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14444                                 ") is out of range"), ptr));
14445                     }
14446 
14447                     // note: at performs range check
14448                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14449                     break;
14450                 }
14451 
14452                 case detail::value_t::null:
14453                 case detail::value_t::string:
14454                 case detail::value_t::boolean:
14455                 case detail::value_t::number_integer:
14456                 case detail::value_t::number_unsigned:
14457                 case detail::value_t::number_float:
14458                 case detail::value_t::binary:
14459                 case detail::value_t::discarded:
14460                 default:
14461                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14462             }
14463         }
14464 
14465         return *ptr;
14466     }
14467 
14468     /*! 
14469     @brief return a const reference to the pointed to value 
14470  
14471     @param[in] ptr  a JSON value 
14472  
14473     @return const reference to the JSON value pointed to by the JSON 
14474     pointer 
14475  
14476     @throw parse_error.106   if an array index begins with '0' 
14477     @throw parse_error.109   if an array index was not a number 
14478     @throw out_of_range.402  if the array index '-' is used 
14479     @throw out_of_range.404  if the JSON pointer can not be resolved 
14480     */
14481     template<typename BasicJsonType>
14482     const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14483     {
14484         for (const auto& reference_token : reference_tokens)
14485         {
14486             switch (ptr->type())
14487             {
14488                 case detail::value_t::object:
14489                 {
14490                     // use unchecked object access
14491                     ptr = &ptr->operator[](reference_token);
14492                     break;
14493                 }
14494 
14495                 case detail::value_t::array:
14496                 {
14497                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14498                     {
14499                         // "-" cannot be used for const access
14500                         JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
14501                     }
14502 
14503                     // use unchecked array access
14504                     ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14505                     break;
14506                 }
14507 
14508                 case detail::value_t::null:
14509                 case detail::value_t::string:
14510                 case detail::value_t::boolean:
14511                 case detail::value_t::number_integer:
14512                 case detail::value_t::number_unsigned:
14513                 case detail::value_t::number_float:
14514                 case detail::value_t::binary:
14515                 case detail::value_t::discarded:
14516                 default:
14517                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14518             }
14519         }
14520 
14521         return *ptr;
14522     }
14523 
14524     /*! 
14525     @throw parse_error.106   if an array index begins with '0' 
14526     @throw parse_error.109   if an array index was not a number 
14527     @throw out_of_range.402  if the array index '-' is used 
14528     @throw out_of_range.404  if the JSON pointer can not be resolved 
14529     */
14530     template<typename BasicJsonType>
14531     const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14532     {
14533         for (const auto& reference_token : reference_tokens)
14534         {
14535             switch (ptr->type())
14536             {
14537                 case detail::value_t::object:
14538                 {
14539                     // note: at performs range check
14540                     ptr = &ptr->at(reference_token);
14541                     break;
14542                 }
14543 
14544                 case detail::value_t::array:
14545                 {
14546                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14547                     {
14548                         // "-" always fails the range check
14549                         JSON_THROW(detail::out_of_range::create(402, detail::concat(
14550                                 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14551                                 ") is out of range"), ptr));
14552                     }
14553 
14554                     // note: at performs range check
14555                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14556                     break;
14557                 }
14558 
14559                 case detail::value_t::null:
14560                 case detail::value_t::string:
14561                 case detail::value_t::boolean:
14562                 case detail::value_t::number_integer:
14563                 case detail::value_t::number_unsigned:
14564                 case detail::value_t::number_float:
14565                 case detail::value_t::binary:
14566                 case detail::value_t::discarded:
14567                 default:
14568                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14569             }
14570         }
14571 
14572         return *ptr;
14573     }
14574 
14575     /*! 
14576     @throw parse_error.106   if an array index begins with '0' 
14577     @throw parse_error.109   if an array index was not a number 
14578     */
14579     template<typename BasicJsonType>
14580     bool contains(const BasicJsonType* ptr) const
14581     {
14582         for (const auto& reference_token : reference_tokens)
14583         {
14584             switch (ptr->type())
14585             {
14586                 case detail::value_t::object:
14587                 {
14588                     if (!ptr->contains(reference_token))
14589                     {
14590                         // we did not find the key in the object
14591                         return false;
14592                     }
14593 
14594                     ptr = &ptr->operator[](reference_token);
14595                     break;
14596                 }
14597 
14598                 case detail::value_t::array:
14599                 {
14600                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14601                     {
14602                         // "-" always fails the range check
14603                         return false;
14604                     }
14605                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14606                     {
14607                         // invalid char
14608                         return false;
14609                     }
14610                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14611                     {
14612                         if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14613                         {
14614                             // first char should be between '1' and '9'
14615                             return false;
14616                         }
14617                         for (std::size_t i = 1; i < reference_token.size(); i++)
14618                         {
14619                             if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14620                             {
14621                                 // other char should be between '0' and '9'
14622                                 return false;
14623                             }
14624                         }
14625                     }
14626 
14627                     const auto idx = array_index<BasicJsonType>(reference_token);
14628                     if (idx >= ptr->size())
14629                     {
14630                         // index out of range
14631                         return false;
14632                     }
14633 
14634                     ptr = &ptr->operator[](idx);
14635                     break;
14636                 }
14637 
14638                 case detail::value_t::null:
14639                 case detail::value_t::string:
14640                 case detail::value_t::boolean:
14641                 case detail::value_t::number_integer:
14642                 case detail::value_t::number_unsigned:
14643                 case detail::value_t::number_float:
14644                 case detail::value_t::binary:
14645                 case detail::value_t::discarded:
14646                 default:
14647                 {
14648                     // we do not expect primitive values if there is still a
14649                     // reference token to process
14650                     return false;
14651                 }
14652             }
14653         }
14654 
14655         // no reference token left means we found a primitive value
14656         return true;
14657     }
14658 
14659     /*! 
14660     @brief split the string input to reference tokens 
14661  
14662     @note This function is only called by the json_pointer constructor. 
14663           All exceptions below are documented there. 
14664  
14665     @throw parse_error.107  if the pointer is not empty or begins with '/' 
14666     @throw parse_error.108  if character '~' is not followed by '0' or '1' 
14667     */
14668     static std::vector<string_t> split(const string_t& reference_string)
14669     {
14670         std::vector<string_t> result;
14671 
14672         // special case: empty reference string -> no reference tokens
14673         if (reference_string.empty())
14674         {
14675             return result;
14676         }
14677 
14678         // check if nonempty reference string begins with slash
14679         if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14680         {
14681             JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14682         }
14683 
14684         // extract the reference tokens:
14685         // - slash: position of the last read slash (or end of string)
14686         // - start: position after the previous slash
14687         for (
14688             // search for the first slash after the first character
14689             std::size_t slash = reference_string.find_first_of('/', 1),
14690             // set the beginning of the first reference token
14691             start = 1;
14692             // we can stop if start == 0 (if slash == string_t::npos)
14693             start != 0;
14694             // set the beginning of the next reference token
14695             // (will eventually be 0 if slash == string_t::npos)
14696             start = (slash == string_t::npos) ? 0 : slash + 1,
14697             // find next slash
14698             slash = reference_string.find_first_of('/', start))
14699         {
14700             // use the text between the beginning of the reference token
14701             // (start) and the last slash (slash).
14702             auto reference_token = reference_string.substr(start, slash - start);
14703 
14704             // check reference tokens are properly escaped
14705             for (std::size_t pos = reference_token.find_first_of('~');
14706                     pos != string_t::npos;
14707                     pos = reference_token.find_first_of('~', pos + 1))
14708             {
14709                 JSON_ASSERT(reference_token[pos] == '~');
14710 
14711                 // ~ must be followed by 0 or 1
14712                 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14713                                          (reference_token[pos + 1] != '0' &&
14714                                           reference_token[pos + 1] != '1')))
14715                 {
14716                     JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14717                 }
14718             }
14719 
14720             // finally, store the reference token
14721             detail::unescape(reference_token);
14722             result.push_back(reference_token);
14723         }
14724 
14725         return result;
14726     }
14727 
14728   private:
14729     /*! 
14730     @param[in] reference_string  the reference string to the current value 
14731     @param[in] value             the value to consider 
14732     @param[in,out] result        the result object to insert values to 
14733  
14734     @note Empty objects or arrays are flattened to `null`. 
14735     */
14736     template<typename BasicJsonType>
14737     static void flatten(const string_t& reference_string,
14738                         const BasicJsonType& value,
14739                         BasicJsonType& result)
14740     {
14741         switch (value.type())
14742         {
14743             case detail::value_t::array:
14744             {
14745                 if (value.m_data.m_value.array->empty())
14746                 {
14747                     // flatten empty array as null
14748                     result[reference_string] = nullptr;
14749                 }
14750                 else
14751                 {
14752                     // iterate array and use index as reference string
14753                     for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14754                     {
14755                         flatten(detail::concat(reference_string, '/', std::to_string(i)),
14756                                 value.m_data.m_value.array->operator[](i), result);
14757                     }
14758                 }
14759                 break;
14760             }
14761 
14762             case detail::value_t::object:
14763             {
14764                 if (value.m_data.m_value.object->empty())
14765                 {
14766                     // flatten empty object as null
14767                     result[reference_string] = nullptr;
14768                 }
14769                 else
14770                 {
14771                     // iterate object and use keys as reference string
14772                     for (const auto& element : *value.m_data.m_value.object)
14773                     {
14774                         flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14775                     }
14776                 }
14777                 break;
14778             }
14779 
14780             case detail::value_t::null:
14781             case detail::value_t::string:
14782             case detail::value_t::boolean:
14783             case detail::value_t::number_integer:
14784             case detail::value_t::number_unsigned:
14785             case detail::value_t::number_float:
14786             case detail::value_t::binary:
14787             case detail::value_t::discarded:
14788             default:
14789             {
14790                 // add primitive value with its reference string
14791                 result[reference_string] = value;
14792                 break;
14793             }
14794         }
14795     }
14796 
14797     /*! 
14798     @param[in] value  flattened JSON 
14799  
14800     @return unflattened JSON 
14801  
14802     @throw parse_error.109 if array index is not a number 
14803     @throw type_error.314  if value is not an object 
14804     @throw type_error.315  if object values are not primitive 
14805     @throw type_error.313  if value cannot be unflattened 
14806     */
14807     template<typename BasicJsonType>
14808     static BasicJsonType
14809     unflatten(const BasicJsonType& value)
14810     {
14811         if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14812         {
14813             JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14814         }
14815 
14816         BasicJsonType result;
14817 
14818         // iterate the JSON object values
14819         for (const auto& element : *value.m_data.m_value.object)
14820         {
14821             if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14822             {
14823                 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14824             }
14825 
14826             // assign value to reference pointed to by JSON pointer; Note that if
14827             // the JSON pointer is "" (i.e., points to the whole value), function
14828             // get_and_create returns a reference to result itself. An assignment
14829             // will then create a primitive value.
14830             json_pointer(element.first).get_and_create(result) = element.second;
14831         }
14832 
14833         return result;
14834     }
14835 
14836     // can't use conversion operator because of ambiguity
14837     json_pointer<string_t> convert() const&
14838     {
14839         json_pointer<string_t> result;
14840         result.reference_tokens = reference_tokens;
14841         return result;
14842     }
14843 
14844     json_pointer<string_t> convert()&&
14845     {
14846         json_pointer<string_t> result;
14847         result.reference_tokens = std::move(reference_tokens);
14848         return result;
14849     }
14850 
14851   public:
14852 #if JSON_HAS_THREE_WAY_COMPARISON
14853     /// @brief compares two JSON pointers for equality
14854     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14855     template<typename RefStringTypeRhs>
14856     bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14857     {
14858         return reference_tokens == rhs.reference_tokens;
14859     }
14860 
14861     /// @brief compares JSON pointer and string for equality
14862     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14863     JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14864     bool operator==(const string_t& rhs) const
14865     {
14866         return *this == json_pointer(rhs);
14867     }
14868 
14869     /// @brief 3-way compares two JSON pointers
14870     template<typename RefStringTypeRhs>
14871     std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14872     {
14873         return  reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14874     }
14875 #else
14876     /// @brief compares two JSON pointers for equality
14877     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14878     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14879     // NOLINTNEXTLINE(readability-redundant-declaration)
14880     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14881                            const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14882 
14883     /// @brief compares JSON pointer and string for equality
14884     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14885     template<typename RefStringTypeLhs, typename StringType>
14886     // NOLINTNEXTLINE(readability-redundant-declaration)
14887     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14888                            const StringType& rhs);
14889 
14890     /// @brief compares string and JSON pointer for equality
14891     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
14892     template<typename RefStringTypeRhs, typename StringType>
14893     // NOLINTNEXTLINE(readability-redundant-declaration)
14894     friend bool operator==(const StringType& lhs,
14895                            const json_pointer<RefStringTypeRhs>& rhs);
14896 
14897     /// @brief compares two JSON pointers for inequality
14898     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14899     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14900     // NOLINTNEXTLINE(readability-redundant-declaration)
14901     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14902                            const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14903 
14904     /// @brief compares JSON pointer and string for inequality
14905     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14906     template<typename RefStringTypeLhs, typename StringType>
14907     // NOLINTNEXTLINE(readability-redundant-declaration)
14908     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14909                            const StringType& rhs);
14910 
14911     /// @brief compares string and JSON pointer for inequality
14912     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
14913     template<typename RefStringTypeRhs, typename StringType>
14914     // NOLINTNEXTLINE(readability-redundant-declaration)
14915     friend bool operator!=(const StringType& lhs,
14916                            const json_pointer<RefStringTypeRhs>& rhs);
14917 
14918     /// @brief compares two JSON pointer for less-than
14919     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14920     // NOLINTNEXTLINE(readability-redundant-declaration)
14921     friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14922                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14923 #endif
14924 
14925   private:
14926     /// the reference tokens
14927     std::vector<string_t> reference_tokens;
14928 };
14929 
14930 #if !JSON_HAS_THREE_WAY_COMPARISON
14931 // functions cannot be defined inside class due to ODR violations
14932 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14933 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14934                        const json_pointer<RefStringTypeRhs>& rhs) noexcept
14935 {
14936     return lhs.reference_tokens == rhs.reference_tokens;
14937 }
14938 
14939 template<typename RefStringTypeLhs,
14940          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14941 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14942 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14943                        const StringType& rhs)
14944 {
14945     return lhs == json_pointer<RefStringTypeLhs>(rhs);
14946 }
14947 
14948 template<typename RefStringTypeRhs,
14949          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14950 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14951 inline bool operator==(const StringType& lhs,
14952                        const json_pointer<RefStringTypeRhs>& rhs)
14953 {
14954     return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14955 }
14956 
14957 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14958 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14959                        const json_pointer<RefStringTypeRhs>& rhs) noexcept
14960 {
14961     return !(lhs == rhs);
14962 }
14963 
14964 template<typename RefStringTypeLhs,
14965          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14966 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14967 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14968                        const StringType& rhs)
14969 {
14970     return !(lhs == rhs);
14971 }
14972 
14973 template<typename RefStringTypeRhs,
14974          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14975 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14976 inline bool operator!=(const StringType& lhs,
14977                        const json_pointer<RefStringTypeRhs>& rhs)
14978 {
14979     return !(lhs == rhs);
14980 }
14981 
14982 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14983 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14984                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
14985 {
14986     return lhs.reference_tokens < rhs.reference_tokens;
14987 }
14988 #endif
14989 
14990 NLOHMANN_JSON_NAMESPACE_END
14991 
14992 // #include <nlohmann/detail/json_ref.hpp>
14993 //     __ _____ _____ _____
14994 //  __|  |   __|     |   | |  JSON for Modern C++
14995 // |  |  |__   |  |  | | | |  version 3.11.3
14996 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14997 //
14998 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
14999 // SPDX-License-Identifier: MIT
15000 
15001 
15002 
15003 #include <initializer_list>
15004 #include <utility>
15005 
15006 // #include <nlohmann/detail/abi_macros.hpp>
15007 
15008 // #include <nlohmann/detail/meta/type_traits.hpp>
15009 
15010 
15011 NLOHMANN_JSON_NAMESPACE_BEGIN
15012 namespace detail
15013 {
15014 
15015 template<typename BasicJsonType>
15016 class json_ref
15017 {
15018   public:
15019     using value_type = BasicJsonType;
15020 
15021     json_ref(value_type&& value)
15022         : owned_value(std::move(value))
15023     {}
15024 
15025     json_ref(const value_type& value)
15026         : value_ref(&value)
15027     {}
15028 
15029     json_ref(std::initializer_list<json_ref> init)
15030         : owned_value(init)
15031     {}
15032 
15033     template <
15034         class... Args,
15035         enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15036     json_ref(Args && ... args)
15037         : owned_value(std::forward<Args>(args)...)
15038     {}
15039 
15040     // class should be movable only
15041     json_ref(json_ref&&) noexcept = default;
15042     json_ref(const json_ref&) = delete;
15043     json_ref& operator=(const json_ref&) = delete;
15044     json_ref& operator=(json_ref&&) = delete;
15045     ~json_ref() = default;
15046 
15047     value_type moved_or_copied() const
15048     {
15049         if (value_ref == nullptr)
15050         {
15051             return std::move(owned_value);
15052         }
15053         return *value_ref;
15054     }
15055 
15056     value_type const& operator*() const
15057     {
15058         return value_ref ? *value_ref : owned_value;
15059     }
15060 
15061     value_type const* operator->() const
15062     {
15063         return &** this;
15064     }
15065 
15066   private:
15067     mutable value_type owned_value = nullptr;
15068     value_type const* value_ref = nullptr;
15069 };
15070 
15071 }  // namespace detail
15072 NLOHMANN_JSON_NAMESPACE_END
15073 
15074 // #include <nlohmann/detail/macro_scope.hpp>
15075 
15076 // #include <nlohmann/detail/string_concat.hpp>
15077 
15078 // #include <nlohmann/detail/string_escape.hpp>
15079 
15080 // #include <nlohmann/detail/meta/cpp_future.hpp>
15081 
15082 // #include <nlohmann/detail/meta/type_traits.hpp>
15083 
15084 // #include <nlohmann/detail/output/binary_writer.hpp>
15085 //     __ _____ _____ _____
15086 //  __|  |   __|     |   | |  JSON for Modern C++
15087 // |  |  |__   |  |  | | | |  version 3.11.3
15088 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
15089 //
15090 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
15091 // SPDX-License-Identifier: MIT
15092 
15093 
15094 
15095 #include <algorithm> // reverse
15096 #include <array> // array
15097 #include <map> // map
15098 #include <cmath> // isnan, isinf
15099 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15100 #include <cstring> // memcpy
15101 #include <limits> // numeric_limits
15102 #include <string> // string
15103 #include <utility> // move
15104 #include <vector> // vector
15105 
15106 // #include <nlohmann/detail/input/binary_reader.hpp>
15107 
15108 // #include <nlohmann/detail/macro_scope.hpp>
15109 
15110 // #include <nlohmann/detail/output/output_adapters.hpp>
15111 //     __ _____ _____ _____
15112 //  __|  |   __|     |   | |  JSON for Modern C++
15113 // |  |  |__   |  |  | | | |  version 3.11.3
15114 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
15115 //
15116 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
15117 // SPDX-License-Identifier: MIT
15118 
15119 
15120 
15121 #include <algorithm> // copy
15122 #include <cstddef> // size_t
15123 #include <iterator> // back_inserter
15124 #include <memory> // shared_ptr, make_shared
15125 #include <string> // basic_string
15126 #include <vector> // vector
15127 
15128 #ifndef JSON_NO_IO
15129     #include <ios>      // streamsize
15130     #include <ostream>  // basic_ostream
15131 #endif  // JSON_NO_IO
15132 
15133 // #include <nlohmann/detail/macro_scope.hpp>
15134 
15135 
15136 NLOHMANN_JSON_NAMESPACE_BEGIN
15137 namespace detail
15138 {
15139 
15140 /// abstract output adapter interface
15141 template<typename CharType> struct output_adapter_protocol
15142 {
15143     virtual void write_character(CharType c) = 0;
15144     virtual void write_characters(const CharType* s, std::size_t length) = 0;
15145     virtual ~output_adapter_protocol() = default;
15146 
15147     output_adapter_protocol() = default;
15148     output_adapter_protocol(const output_adapter_protocol&) = default;
15149     output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
15150     output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
15151     output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15152 };
15153 
15154 /// a type to simplify interfaces
15155 template<typename CharType>
15156 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15157 
15158 /// output adapter for byte vectors
15159 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15160 class output_vector_adapter : public output_adapter_protocol<CharType>
15161 {
15162   public:
15163     explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15164         : v(vec)
15165     {}
15166 
15167     void write_character(CharType c) override
15168     {
15169         v.push_back(c);
15170     }
15171 
15172     JSON_HEDLEY_NON_NULL(2)
15173     void write_characters(const CharType* s, std::size_t length) override
15174     {
15175         v.insert(v.end(), s, s + length);
15176     }
15177 
15178   private:
15179     std::vector<CharType, AllocatorType>& v;
15180 };
15181 
15182 #ifndef JSON_NO_IO
15183 /// output adapter for output streams
15184 template<typename CharType>
15185 class output_stream_adapter : public output_adapter_protocol<CharType>
15186 {
15187   public:
15188     explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15189         : stream(s)
15190     {}
15191 
15192     void write_character(CharType c) override
15193     {
15194         stream.put(c);
15195     }
15196 
15197     JSON_HEDLEY_NON_NULL(2)
15198     void write_characters(const CharType* s, std::size_t length) override
15199     {
15200         stream.write(s, static_cast<std::streamsize>(length));
15201     }
15202 
15203   private:
15204     std::basic_ostream<CharType>& stream;
15205 };
15206 #endif  // JSON_NO_IO
15207 
15208 /// output adapter for basic_string
15209 template<typename CharType, typename StringType = std::basic_string<CharType>>
15210 class output_string_adapter : public output_adapter_protocol<CharType>
15211 {
15212   public:
15213     explicit output_string_adapter(StringType& s) noexcept
15214         : str(s)
15215     {}
15216 
15217     void write_character(CharType c) override
15218     {
15219         str.push_back(c);
15220     }
15221 
15222     JSON_HEDLEY_NON_NULL(2)
15223     void write_characters(const CharType* s, std::size_t length) override
15224     {
15225         str.append(s, length);
15226     }
15227 
15228   private:
15229     StringType& str;
15230 };
15231 
15232 template<typename CharType, typename StringType = std::basic_string<CharType>>
15233 class output_adapter
15234 {
15235   public:
15236     template<typename AllocatorType = std::allocator<CharType>>
15237     output_adapter(std::vector<CharType, AllocatorType>& vec)
15238         : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15239 
15240 #ifndef JSON_NO_IO
15241     output_adapter(std::basic_ostream<CharType>& s)
15242         : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15243 #endif  // JSON_NO_IO
15244 
15245     output_adapter(StringType& s)
15246         : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15247 
15248     operator output_adapter_t<CharType>()
15249     {
15250         return oa;
15251     }
15252 
15253   private:
15254     output_adapter_t<CharType> oa = nullptr;
15255 };
15256 
15257 }  // namespace detail
15258 NLOHMANN_JSON_NAMESPACE_END
15259 
15260 // #include <nlohmann/detail/string_concat.hpp>
15261 
15262 
15263 NLOHMANN_JSON_NAMESPACE_BEGIN
15264 namespace detail
15265 {
15266 
15267 ///////////////////
15268 // binary writer //
15269 ///////////////////
15270 
15271 /*! 
15272 @brief serialization to CBOR and MessagePack values 
15273 */
15274 template<typename BasicJsonType, typename CharType>
15275 class binary_writer
15276 {
15277     using string_t = typename BasicJsonType::string_t;
15278     using binary_t = typename BasicJsonType::binary_t;
15279     using number_float_t = typename BasicJsonType::number_float_t;
15280 
15281   public:
15282     /*! 
15283     @brief create a binary writer 
15284  
15285     @param[in] adapter  output adapter to write to 
15286     */
15287     explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15288     {
15289         JSON_ASSERT(oa);
15290     }
15291 
15292     /*! 
15293     @param[in] j  JSON value to serialize 
15294     @pre       j.type() == value_t::object 
15295     */
15296     void write_bson(const BasicJsonType& j)
15297     {
15298         switch (j.type())
15299         {
15300             case value_t::object:
15301             {
15302                 write_bson_object(*j.m_data.m_value.object);
15303                 break;
15304             }
15305 
15306             case value_t::null:
15307             case value_t::array:
15308             case value_t::string:
15309             case value_t::boolean:
15310             case value_t::number_integer:
15311             case value_t::number_unsigned:
15312             case value_t::number_float:
15313             case value_t::binary:
15314             case value_t::discarded:
15315             default:
15316             {
15317                 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15318             }
15319         }
15320     }
15321 
15322     /*! 
15323     @param[in] j  JSON value to serialize 
15324     */
15325     void write_cbor(const BasicJsonType& j)
15326     {
15327         switch (j.type())
15328         {
15329             case value_t::null:
15330             {
15331                 oa->write_character(to_char_type(0xF6));
15332                 break;
15333             }
15334 
15335             case value_t::boolean:
15336             {
15337                 oa->write_character(j.m_data.m_value.boolean
15338                                     ? to_char_type(0xF5)
15339                                     : to_char_type(0xF4));
15340                 break;
15341             }
15342 
15343             case value_t::number_integer:
15344             {
15345                 if (j.m_data.m_value.number_integer >= 0)
15346                 {
15347                     // CBOR does not differentiate between positive signed
15348                     // integers and unsigned integers. Therefore, we used the
15349                     // code from the value_t::number_unsigned case here.
15350                     if (j.m_data.m_value.number_integer <= 0x17)
15351                     {
15352                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15353                     }
15354                     else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15355                     {
15356                         oa->write_character(to_char_type(0x18));
15357                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15358                     }
15359                     else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15360                     {
15361                         oa->write_character(to_char_type(0x19));
15362                         write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15363                     }
15364                     else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15365                     {
15366                         oa->write_character(to_char_type(0x1A));
15367                         write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15368                     }
15369                     else
15370                     {
15371                         oa->write_character(to_char_type(0x1B));
15372                         write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15373                     }
15374                 }
15375                 else
15376                 {
15377                     // The conversions below encode the sign in the first
15378                     // byte, and the value is converted to a positive number.
15379                     const auto positive_number = -1 - j.m_data.m_value.number_integer;
15380                     if (j.m_data.m_value.number_integer >= -24)
15381                     {
15382                         write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15383                     }
15384                     else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15385                     {
15386                         oa->write_character(to_char_type(0x38));
15387                         write_number(static_cast<std::uint8_t>(positive_number));
15388                     }
15389                     else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15390                     {
15391                         oa->write_character(to_char_type(0x39));
15392                         write_number(static_cast<std::uint16_t>(positive_number));
15393                     }
15394                     else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15395                     {
15396                         oa->write_character(to_char_type(0x3A));
15397                         write_number(static_cast<std::uint32_t>(positive_number));
15398                     }
15399                     else
15400                     {
15401                         oa->write_character(to_char_type(0x3B));
15402                         write_number(static_cast<std::uint64_t>(positive_number));
15403                     }
15404                 }
15405                 break;
15406             }
15407 
15408             case value_t::number_unsigned:
15409             {
15410                 if (j.m_data.m_value.number_unsigned <= 0x17)
15411                 {
15412                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15413                 }
15414                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15415                 {
15416                     oa->write_character(to_char_type(0x18));
15417                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15418                 }
15419                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15420                 {
15421                     oa->write_character(to_char_type(0x19));
15422                     write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15423                 }
15424                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15425                 {
15426                     oa->write_character(to_char_type(0x1A));
15427                     write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15428                 }
15429                 else
15430                 {
15431                     oa->write_character(to_char_type(0x1B));
15432                     write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15433                 }
15434                 break;
15435             }
15436 
15437             case value_t::number_float:
15438             {
15439                 if (std::isnan(j.m_data.m_value.number_float))
15440                 {
15441                     // NaN is 0xf97e00 in CBOR
15442                     oa->write_character(to_char_type(0xF9));
15443                     oa->write_character(to_char_type(0x7E));
15444                     oa->write_character(to_char_type(0x00));
15445                 }
15446                 else if (std::isinf(j.m_data.m_value.number_float))
15447                 {
15448                     // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15449                     oa->write_character(to_char_type(0xf9));
15450                     oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15451                     oa->write_character(to_char_type(0x00));
15452                 }
15453                 else
15454                 {
15455                     write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15456                 }
15457                 break;
15458             }
15459 
15460             case value_t::string:
15461             {
15462                 // step 1: write control byte and the string length
15463                 const auto N = j.m_data.m_value.string->size();
15464                 if (N <= 0x17)
15465                 {
15466                     write_number(static_cast<std::uint8_t>(0x60 + N));
15467                 }
15468                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15469                 {
15470                     oa->write_character(to_char_type(0x78));
15471                     write_number(static_cast<std::uint8_t>(N));
15472                 }
15473                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15474                 {
15475                     oa->write_character(to_char_type(0x79));
15476                     write_number(static_cast<std::uint16_t>(N));
15477                 }
15478                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15479                 {
15480                     oa->write_character(to_char_type(0x7A));
15481                     write_number(static_cast<std::uint32_t>(N));
15482                 }
15483                 // LCOV_EXCL_START
15484                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15485                 {
15486                     oa->write_character(to_char_type(0x7B));
15487                     write_number(static_cast<std::uint64_t>(N));
15488                 }
15489                 // LCOV_EXCL_STOP
15490 
15491                 // step 2: write the string
15492                 oa->write_characters(
15493                     reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15494                     j.m_data.m_value.string->size());
15495                 break;
15496             }
15497 
15498             case value_t::array:
15499             {
15500                 // step 1: write control byte and the array size
15501                 const auto N = j.m_data.m_value.array->size();
15502                 if (N <= 0x17)
15503                 {
15504                     write_number(static_cast<std::uint8_t>(0x80 + N));
15505                 }
15506                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15507                 {
15508                     oa->write_character(to_char_type(0x98));
15509                     write_number(static_cast<std::uint8_t>(N));
15510                 }
15511                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15512                 {
15513                     oa->write_character(to_char_type(0x99));
15514                     write_number(static_cast<std::uint16_t>(N));
15515                 }
15516                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15517                 {
15518                     oa->write_character(to_char_type(0x9A));
15519                     write_number(static_cast<std::uint32_t>(N));
15520                 }
15521                 // LCOV_EXCL_START
15522                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15523                 {
15524                     oa->write_character(to_char_type(0x9B));
15525                     write_number(static_cast<std::uint64_t>(N));
15526                 }
15527                 // LCOV_EXCL_STOP
15528 
15529                 // step 2: write each element
15530                 for (const auto& el : *j.m_data.m_value.array)
15531                 {
15532                     write_cbor(el);
15533                 }
15534                 break;
15535             }
15536 
15537             case value_t::binary:
15538             {
15539                 if (j.m_data.m_value.binary->has_subtype())
15540                 {
15541                     if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15542                     {
15543                         write_number(static_cast<std::uint8_t>(0xd8));
15544                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15545                     }
15546                     else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15547                     {
15548                         write_number(static_cast<std::uint8_t>(0xd9));
15549                         write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15550                     }
15551                     else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15552                     {
15553                         write_number(static_cast<std::uint8_t>(0xda));
15554                         write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15555                     }
15556                     else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15557                     {
15558                         write_number(static_cast<std::uint8_t>(0xdb));
15559                         write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15560                     }
15561                 }
15562 
15563                 // step 1: write control byte and the binary array size
15564                 const auto N = j.m_data.m_value.binary->size();
15565                 if (N <= 0x17)
15566                 {
15567                     write_number(static_cast<std::uint8_t>(0x40 + N));
15568                 }
15569                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15570                 {
15571                     oa->write_character(to_char_type(0x58));
15572                     write_number(static_cast<std::uint8_t>(N));
15573                 }
15574                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15575                 {
15576                     oa->write_character(to_char_type(0x59));
15577                     write_number(static_cast<std::uint16_t>(N));
15578                 }
15579                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15580                 {
15581                     oa->write_character(to_char_type(0x5A));
15582                     write_number(static_cast<std::uint32_t>(N));
15583                 }
15584                 // LCOV_EXCL_START
15585                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15586                 {
15587                     oa->write_character(to_char_type(0x5B));
15588                     write_number(static_cast<std::uint64_t>(N));
15589                 }
15590                 // LCOV_EXCL_STOP
15591 
15592                 // step 2: write each element
15593                 oa->write_characters(
15594                     reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15595                     N);
15596 
15597                 break;
15598             }
15599 
15600             case value_t::object:
15601             {
15602                 // step 1: write control byte and the object size
15603                 const auto N = j.m_data.m_value.object->size();
15604                 if (N <= 0x17)
15605                 {
15606                     write_number(static_cast<std::uint8_t>(0xA0 + N));
15607                 }
15608                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15609                 {
15610                     oa->write_character(to_char_type(0xB8));
15611                     write_number(static_cast<std::uint8_t>(N));
15612                 }
15613                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15614                 {
15615                     oa->write_character(to_char_type(0xB9));
15616                     write_number(static_cast<std::uint16_t>(N));
15617                 }
15618                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15619                 {
15620                     oa->write_character(to_char_type(0xBA));
15621                     write_number(static_cast<std::uint32_t>(N));
15622                 }
15623                 // LCOV_EXCL_START
15624                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15625                 {
15626                     oa->write_character(to_char_type(0xBB));
15627                     write_number(static_cast<std::uint64_t>(N));
15628                 }
15629                 // LCOV_EXCL_STOP
15630 
15631                 // step 2: write each element
15632                 for (const auto& el : *j.m_data.m_value.object)
15633                 {
15634                     write_cbor(el.first);
15635                     write_cbor(el.second);
15636                 }
15637                 break;
15638             }
15639 
15640             case value_t::discarded:
15641             default:
15642                 break;
15643         }
15644     }
15645 
15646     /*! 
15647     @param[in] j  JSON value to serialize 
15648     */
15649     void write_msgpack(const BasicJsonType& j)
15650     {
15651         switch (j.type())
15652         {
15653             case value_t::null: // nil
15654             {
15655                 oa->write_character(to_char_type(0xC0));
15656                 break;
15657             }
15658 
15659             case value_t::boolean: // true and false
15660             {
15661                 oa->write_character(j.m_data.m_value.boolean
15662                                     ? to_char_type(0xC3)
15663                                     : to_char_type(0xC2));
15664                 break;
15665             }
15666 
15667             case value_t::number_integer:
15668             {
15669                 if (j.m_data.m_value.number_integer >= 0)
15670                 {
15671                     // MessagePack does not differentiate between positive
15672                     // signed integers and unsigned integers. Therefore, we used
15673                     // the code from the value_t::number_unsigned case here.
15674                     if (j.m_data.m_value.number_unsigned < 128)
15675                     {
15676                         // positive fixnum
15677                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15678                     }
15679                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15680                     {
15681                         // uint 8
15682                         oa->write_character(to_char_type(0xCC));
15683                         write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15684                     }
15685                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15686                     {
15687                         // uint 16
15688                         oa->write_character(to_char_type(0xCD));
15689                         write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15690                     }
15691                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15692                     {
15693                         // uint 32
15694                         oa->write_character(to_char_type(0xCE));
15695                         write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15696                     }
15697                     else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15698                     {
15699                         // uint 64
15700                         oa->write_character(to_char_type(0xCF));
15701                         write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15702                     }
15703                 }
15704                 else
15705                 {
15706                     if (j.m_data.m_value.number_integer >= -32)
15707                     {
15708                         // negative fixnum
15709                         write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15710                     }
15711                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15712                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15713                     {
15714                         // int 8
15715                         oa->write_character(to_char_type(0xD0));
15716                         write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15717                     }
15718                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15719                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15720                     {
15721                         // int 16
15722                         oa->write_character(to_char_type(0xD1));
15723                         write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15724                     }
15725                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15726                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15727                     {
15728                         // int 32
15729                         oa->write_character(to_char_type(0xD2));
15730                         write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15731                     }
15732                     else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15733                              j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15734                     {
15735                         // int 64
15736                         oa->write_character(to_char_type(0xD3));
15737                         write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15738                     }
15739                 }
15740                 break;
15741             }
15742 
15743             case value_t::number_unsigned:
15744             {
15745                 if (j.m_data.m_value.number_unsigned < 128)
15746                 {
15747                     // positive fixnum
15748                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15749                 }
15750                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15751                 {
15752                     // uint 8
15753                     oa->write_character(to_char_type(0xCC));
15754                     write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15755                 }
15756                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15757                 {
15758                     // uint 16
15759                     oa->write_character(to_char_type(0xCD));
15760                     write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15761                 }
15762                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15763                 {
15764                     // uint 32
15765                     oa->write_character(to_char_type(0xCE));
15766                     write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15767                 }
15768                 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15769                 {
15770                     // uint 64
15771                     oa->write_character(to_char_type(0xCF));
15772                     write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15773                 }
15774                 break;
15775             }
15776 
15777             case value_t::number_float:
15778             {
15779                 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15780                 break;
15781             }
15782 
15783             case value_t::string:
15784             {
15785                 // step 1: write control byte and the string length
15786                 const auto N = j.m_data.m_value.string->size();
15787                 if (N <= 31)
15788                 {
15789                     // fixstr
15790                     write_number(static_cast<std::uint8_t>(0xA0 | N));
15791                 }
15792                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15793                 {
15794                     // str 8
15795                     oa->write_character(to_char_type(0xD9));
15796                     write_number(static_cast<std::uint8_t>(N));
15797                 }
15798                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15799                 {
15800                     // str 16
15801                     oa->write_character(to_char_type(0xDA));
15802                     write_number(static_cast<std::uint16_t>(N));
15803                 }
15804                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15805                 {
15806                     // str 32
15807                     oa->write_character(to_char_type(0xDB));
15808                     write_number(static_cast<std::uint32_t>(N));
15809                 }
15810 
15811                 // step 2: write the string
15812                 oa->write_characters(
15813                     reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15814                     j.m_data.m_value.string->size());
15815                 break;
15816             }
15817 
15818             case value_t::array:
15819             {
15820                 // step 1: write control byte and the array size
15821                 const auto N = j.m_data.m_value.array->size();
15822                 if (N <= 15)
15823                 {
15824                     // fixarray
15825                     write_number(static_cast<std::uint8_t>(0x90 | N));
15826                 }
15827                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15828                 {
15829                     // array 16
15830                     oa->write_character(to_char_type(0xDC));
15831                     write_number(static_cast<std::uint16_t>(N));
15832                 }
15833                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15834                 {
15835                     // array 32
15836                     oa->write_character(to_char_type(0xDD));
15837                     write_number(static_cast<std::uint32_t>(N));
15838                 }
15839 
15840                 // step 2: write each element
15841                 for (const auto& el : *j.m_data.m_value.array)
15842                 {
15843                     write_msgpack(el);
15844                 }
15845                 break;
15846             }
15847 
15848             case value_t::binary:
15849             {
15850                 // step 0: determine if the binary type has a set subtype to
15851                 // determine whether to use the ext or fixext types
15852                 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15853 
15854                 // step 1: write control byte and the byte string length
15855                 const auto N = j.m_data.m_value.binary->size();
15856                 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15857                 {
15858                     std::uint8_t output_type{};
15859                     bool fixed = true;
15860                     if (use_ext)
15861                     {
15862                         switch (N)
15863                         {
15864                             case 1:
15865                                 output_type = 0xD4; // fixext 1
15866                                 break;
15867                             case 2:
15868                                 output_type = 0xD5; // fixext 2
15869                                 break;
15870                             case 4:
15871                                 output_type = 0xD6; // fixext 4
15872                                 break;
15873                             case 8:
15874                                 output_type = 0xD7; // fixext 8
15875                                 break;
15876                             case 16:
15877                                 output_type = 0xD8; // fixext 16
15878                                 break;
15879                             default:
15880                                 output_type = 0xC7; // ext 8
15881                                 fixed = false;
15882                                 break;
15883                         }
15884 
15885                     }
15886                     else
15887                     {
15888                         output_type = 0xC4; // bin 8
15889                         fixed = false;
15890                     }
15891 
15892                     oa->write_character(to_char_type(output_type));
15893                     if (!fixed)
15894                     {
15895                         write_number(static_cast<std::uint8_t>(N));
15896                     }
15897                 }
15898                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15899                 {
15900                     const std::uint8_t output_type = use_ext
15901                                                      ? 0xC8 // ext 16
15902                                                      : 0xC5; // bin 16
15903 
15904                     oa->write_character(to_char_type(output_type));
15905                     write_number(static_cast<std::uint16_t>(N));
15906                 }
15907                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15908                 {
15909                     const std::uint8_t output_type = use_ext
15910                                                      ? 0xC9 // ext 32
15911                                                      : 0xC6; // bin 32
15912 
15913                     oa->write_character(to_char_type(output_type));
15914                     write_number(static_cast<std::uint32_t>(N));
15915                 }
15916 
15917                 // step 1.5: if this is an ext type, write the subtype
15918                 if (use_ext)
15919                 {
15920                     write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15921                 }
15922 
15923                 // step 2: write the byte string
15924                 oa->write_characters(
15925                     reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15926                     N);
15927 
15928                 break;
15929             }
15930 
15931             case value_t::object:
15932             {
15933                 // step 1: write control byte and the object size
15934                 const auto N = j.m_data.m_value.object->size();
15935                 if (N <= 15)
15936                 {
15937                     // fixmap
15938                     write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15939                 }
15940                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15941                 {
15942                     // map 16
15943                     oa->write_character(to_char_type(0xDE));
15944                     write_number(static_cast<std::uint16_t>(N));
15945                 }
15946                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15947                 {
15948                     // map 32
15949                     oa->write_character(to_char_type(0xDF));
15950                     write_number(static_cast<std::uint32_t>(N));
15951                 }
15952 
15953                 // step 2: write each element
15954                 for (const auto& el : *j.m_data.m_value.object)
15955                 {
15956                     write_msgpack(el.first);
15957                     write_msgpack(el.second);
15958                 }
15959                 break;
15960             }
15961 
15962             case value_t::discarded:
15963             default:
15964                 break;
15965         }
15966     }
15967 
15968     /*! 
15969     @param[in] j  JSON value to serialize 
15970     @param[in] use_count   whether to use '#' prefixes (optimized format) 
15971     @param[in] use_type    whether to use '$' prefixes (optimized format) 
15972     @param[in] add_prefix  whether prefixes need to be used for this value 
15973     @param[in] use_bjdata  whether write in BJData format, default is false 
15974     */
15975     void write_ubjson(const BasicJsonType& j, const bool use_count,
15976                       const bool use_type, const bool add_prefix = true,
15977                       const bool use_bjdata = false)
15978     {
15979         switch (j.type())
15980         {
15981             case value_t::null:
15982             {
15983                 if (add_prefix)
15984                 {
15985                     oa->write_character(to_char_type('Z'));
15986                 }
15987                 break;
15988             }
15989 
15990             case value_t::boolean:
15991             {
15992                 if (add_prefix)
15993                 {
15994                     oa->write_character(j.m_data.m_value.boolean
15995                                         ? to_char_type('T')
15996                                         : to_char_type('F'));
15997                 }
15998                 break;
15999             }
16000 
16001             case value_t::number_integer:
16002             {
16003                 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16004                 break;
16005             }
16006 
16007             case value_t::number_unsigned:
16008             {
16009                 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16010                 break;
16011             }
16012 
16013             case value_t::number_float:
16014             {
16015                 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16016                 break;
16017             }
16018 
16019             case value_t::string:
16020             {
16021                 if (add_prefix)
16022                 {
16023                     oa->write_character(to_char_type('S'));
16024                 }
16025                 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16026                 oa->write_characters(
16027                     reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16028                     j.m_data.m_value.string->size());
16029                 break;
16030             }
16031 
16032             case value_t::array:
16033             {
16034                 if (add_prefix)
16035                 {
16036                     oa->write_character(to_char_type('['));
16037                 }
16038 
16039                 bool prefix_required = true;
16040                 if (use_type && !j.m_data.m_value.array->empty())
16041                 {
16042                     JSON_ASSERT(use_count);
16043                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16044                     const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16045                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
16046                     {
16047                         return ubjson_prefix(v, use_bjdata) == first_prefix;
16048                     });
16049 
16050                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16051 
16052                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16053                     {
16054                         prefix_required = false;
16055                         oa->write_character(to_char_type('$'));
16056                         oa->write_character(first_prefix);
16057                     }
16058                 }
16059 
16060                 if (use_count)
16061                 {
16062                     oa->write_character(to_char_type('#'));
16063                     write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16064                 }
16065 
16066                 for (const auto& el : *j.m_data.m_value.array)
16067                 {
16068                     write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
16069                 }
16070 
16071                 if (!use_count)
16072                 {
16073                     oa->write_character(to_char_type(']'));
16074                 }
16075 
16076                 break;
16077             }
16078 
16079             case value_t::binary:
16080             {
16081                 if (add_prefix)
16082                 {
16083                     oa->write_character(to_char_type('['));
16084                 }
16085 
16086                 if (use_type && !j.m_data.m_value.binary->empty())
16087                 {
16088                     JSON_ASSERT(use_count);
16089                     oa->write_character(to_char_type('$'));
16090                     oa->write_character('U');
16091                 }
16092 
16093                 if (use_count)
16094                 {
16095                     oa->write_character(to_char_type('#'));
16096                     write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16097                 }
16098 
16099                 if (use_type)
16100                 {
16101                     oa->write_characters(
16102                         reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16103                         j.m_data.m_value.binary->size());
16104                 }
16105                 else
16106                 {
16107                     for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16108                     {
16109                         oa->write_character(to_char_type('U'));
16110                         oa->write_character(j.m_data.m_value.binary->data()[i]);
16111                     }
16112                 }
16113 
16114                 if (!use_count)
16115                 {
16116                     oa->write_character(to_char_type(']'));
16117                 }
16118 
16119                 break;
16120             }
16121 
16122             case value_t::object:
16123             {
16124                 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
16125                 {
16126                     if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type))  // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
16127                     {
16128                         break;
16129                     }
16130                 }
16131 
16132                 if (add_prefix)
16133                 {
16134                     oa->write_character(to_char_type('{'));
16135                 }
16136 
16137                 bool prefix_required = true;
16138                 if (use_type && !j.m_data.m_value.object->empty())
16139                 {
16140                     JSON_ASSERT(use_count);
16141                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16142                     const bool same_prefix = std::all_of(j.begin(), j.end(),
16143                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
16144                     {
16145                         return ubjson_prefix(v, use_bjdata) == first_prefix;
16146                     });
16147 
16148                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16149 
16150                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16151                     {
16152                         prefix_required = false;
16153                         oa->write_character(to_char_type('$'));
16154                         oa->write_character(first_prefix);
16155                     }
16156                 }
16157 
16158                 if (use_count)
16159                 {
16160                     oa->write_character(to_char_type('#'));
16161                     write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16162                 }
16163 
16164                 for (const auto& el : *j.m_data.m_value.object)
16165                 {
16166                     write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16167                     oa->write_characters(
16168                         reinterpret_cast<const CharType*>(el.first.c_str()),
16169                         el.first.size());
16170                     write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
16171                 }
16172 
16173                 if (!use_count)
16174                 {
16175                     oa->write_character(to_char_type('}'));
16176                 }
16177 
16178                 break;
16179             }
16180 
16181             case value_t::discarded:
16182             default:
16183                 break;
16184         }
16185     }
16186 
16187   private:
16188     //////////
16189     // BSON //
16190     //////////
16191 
16192     /*! 
16193     @return The size of a BSON document entry header, including the id marker 
16194             and the entry name size (and its null-terminator). 
16195     */
16196     static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16197     {
16198         const auto it = name.find(static_cast<typename string_t::value_type>(0));
16199         if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16200         {
16201             JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16202             static_cast<void>(j);
16203         }
16204 
16205         return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16206     }
16207 
16208     /*! 
16209     @brief Writes the given @a element_type and @a name to the output adapter 
16210     */
16211     void write_bson_entry_header(const string_t& name,
16212                                  const std::uint8_t element_type)
16213     {
16214         oa->write_character(to_char_type(element_type)); // boolean
16215         oa->write_characters(
16216             reinterpret_cast<const CharType*>(name.c_str()),
16217             name.size() + 1u);
16218     }
16219 
16220     /*! 
16221     @brief Writes a BSON element with key @a name and boolean value @a value 
16222     */
16223     void write_bson_boolean(const string_t& name,
16224                             const bool value)
16225     {
16226         write_bson_entry_header(name, 0x08);
16227         oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16228     }
16229 
16230     /*! 
16231     @brief Writes a BSON element with key @a name and double value @a value 
16232     */
16233     void write_bson_double(const string_t& name,
16234                            const double value)
16235     {
16236         write_bson_entry_header(name, 0x01);
16237         write_number<double>(value, true);
16238     }
16239 
16240     /*! 
16241     @return The size of the BSON-encoded string in @a value 
16242     */
16243     static std::size_t calc_bson_string_size(const string_t& value)
16244     {
16245         return sizeof(std::int32_t) + value.size() + 1ul;
16246     }
16247 
16248     /*! 
16249     @brief Writes a BSON element with key @a name and string value @a value 
16250     */
16251     void write_bson_string(const string_t& name,
16252                            const string_t& value)
16253     {
16254         write_bson_entry_header(name, 0x02);
16255 
16256         write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16257         oa->write_characters(
16258             reinterpret_cast<const CharType*>(value.c_str()),
16259             value.size() + 1);
16260     }
16261 
16262     /*! 
16263     @brief Writes a BSON element with key @a name and null value 
16264     */
16265     void write_bson_null(const string_t& name)
16266     {
16267         write_bson_entry_header(name, 0x0A);
16268     }
16269 
16270     /*! 
16271     @return The size of the BSON-encoded integer @a value 
16272     */
16273     static std::size_t calc_bson_integer_size(const std::int64_t value)
16274     {
16275         return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16276                ? sizeof(std::int32_t)
16277                : sizeof(std::int64_t);
16278     }
16279 
16280     /*! 
16281     @brief Writes a BSON element with key @a name and integer @a value 
16282     */
16283     void write_bson_integer(const string_t& name,
16284                             const std::int64_t value)
16285     {
16286         if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16287         {
16288             write_bson_entry_header(name, 0x10); // int32
16289             write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16290         }
16291         else
16292         {
16293             write_bson_entry_header(name, 0x12); // int64
16294             write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16295         }
16296     }
16297 
16298     /*! 
16299     @return The size of the BSON-encoded unsigned integer in @a j 
16300     */
16301     static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16302     {
16303         return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16304                ? sizeof(std::int32_t)
16305                : sizeof(std::int64_t);
16306     }
16307 
16308     /*! 
16309     @brief Writes a BSON element with key @a name and unsigned @a value 
16310     */
16311     void write_bson_unsigned(const string_t& name,
16312                              const BasicJsonType& j)
16313     {
16314         if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16315         {
16316             write_bson_entry_header(name, 0x10 /* int32 */);
16317             write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16318         }
16319         else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16320         {
16321             write_bson_entry_header(name, 0x12 /* int64 */);
16322             write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16323         }
16324         else
16325         {
16326             JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16327         }
16328     }
16329 
16330     /*! 
16331     @brief Writes a BSON element with key @a name and object @a value 
16332     */
16333     void write_bson_object_entry(const string_t& name,
16334                                  const typename BasicJsonType::object_t& value)
16335     {
16336         write_bson_entry_header(name, 0x03); // object
16337         write_bson_object(value);
16338     }
16339 
16340     /*! 
16341     @return The size of the BSON-encoded array @a value 
16342     */
16343     static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16344     {
16345         std::size_t array_index = 0ul;
16346 
16347         const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
16348         {
16349             return result + calc_bson_element_size(std::to_string(array_index++), el);
16350         });
16351 
16352         return sizeof(std::int32_t) + embedded_document_size + 1ul;
16353     }
16354 
16355     /*! 
16356     @return The size of the BSON-encoded binary array @a value 
16357     */
16358     static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16359     {
16360         return sizeof(std::int32_t) + value.size() + 1ul;
16361     }
16362 
16363     /*! 
16364     @brief Writes a BSON element with key @a name and array @a value 
16365     */
16366     void write_bson_array(const string_t& name,
16367                           const typename BasicJsonType::array_t& value)
16368     {
16369         write_bson_entry_header(name, 0x04); // array
16370         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16371 
16372         std::size_t array_index = 0ul;
16373 
16374         for (const auto& el : value)
16375         {
16376             write_bson_element(std::to_string(array_index++), el);
16377         }
16378 
16379         oa->write_character(to_char_type(0x00));
16380     }
16381 
16382     /*! 
16383     @brief Writes a BSON element with key @a name and binary value @a value 
16384     */
16385     void write_bson_binary(const string_t& name,
16386                            const binary_t& value)
16387     {
16388         write_bson_entry_header(name, 0x05);
16389 
16390         write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16391         write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16392 
16393         oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16394     }
16395 
16396     /*! 
16397     @brief Calculates the size necessary to serialize the JSON value @a j with its @a name 
16398     @return The calculated size for the BSON document entry for @a j with the given @a name. 
16399     */
16400     static std::size_t calc_bson_element_size(const string_t& name,
16401             const BasicJsonType& j)
16402     {
16403         const auto header_size = calc_bson_entry_header_size(name, j);
16404         switch (j.type())
16405         {
16406             case value_t::object:
16407                 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16408 
16409             case value_t::array:
16410                 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16411 
16412             case value_t::binary:
16413                 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16414 
16415             case value_t::boolean:
16416                 return header_size + 1ul;
16417 
16418             case value_t::number_float:
16419                 return header_size + 8ul;
16420 
16421             case value_t::number_integer:
16422                 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16423 
16424             case value_t::number_unsigned:
16425                 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16426 
16427             case value_t::string:
16428                 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16429 
16430             case value_t::null:
16431                 return header_size + 0ul;
16432 
16433             // LCOV_EXCL_START
16434             case value_t::discarded:
16435             default:
16436                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16437                 return 0ul;
16438                 // LCOV_EXCL_STOP
16439         }
16440     }
16441 
16442     /*! 
16443     @brief Serializes the JSON value @a j to BSON and associates it with the 
16444            key @a name. 
16445     @param name The name to associate with the JSON entity @a j within the 
16446                 current BSON document 
16447     */
16448     void write_bson_element(const string_t& name,
16449                             const BasicJsonType& j)
16450     {
16451         switch (j.type())
16452         {
16453             case value_t::object:
16454                 return write_bson_object_entry(name, *j.m_data.m_value.object);
16455 
16456             case value_t::array:
16457                 return write_bson_array(name, *j.m_data.m_value.array);
16458 
16459             case value_t::binary:
16460                 return write_bson_binary(name, *j.m_data.m_value.binary);
16461 
16462             case value_t::boolean:
16463                 return write_bson_boolean(name, j.m_data.m_value.boolean);
16464 
16465             case value_t::number_float:
16466                 return write_bson_double(name, j.m_data.m_value.number_float);
16467 
16468             case value_t::number_integer:
16469                 return write_bson_integer(name, j.m_data.m_value.number_integer);
16470 
16471             case value_t::number_unsigned:
16472                 return write_bson_unsigned(name, j);
16473 
16474             case value_t::string:
16475                 return write_bson_string(name, *j.m_data.m_value.string);
16476 
16477             case value_t::null:
16478                 return write_bson_null(name);
16479 
16480             // LCOV_EXCL_START
16481             case value_t::discarded:
16482             default:
16483                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16484                 return;
16485                 // LCOV_EXCL_STOP
16486         }
16487     }
16488 
16489     /*! 
16490     @brief Calculates the size of the BSON serialization of the given 
16491            JSON-object @a j. 
16492     @param[in] value  JSON value to serialize 
16493     @pre       value.type() == value_t::object 
16494     */
16495     static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16496     {
16497         const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16498                                           [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16499         {
16500             return result += calc_bson_element_size(el.first, el.second);
16501         });
16502 
16503         return sizeof(std::int32_t) + document_size + 1ul;
16504     }
16505 
16506     /*! 
16507     @param[in] value  JSON value to serialize 
16508     @pre       value.type() == value_t::object 
16509     */
16510     void write_bson_object(const typename BasicJsonType::object_t& value)
16511     {
16512         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16513 
16514         for (const auto& el : value)
16515         {
16516             write_bson_element(el.first, el.second);
16517         }
16518 
16519         oa->write_character(to_char_type(0x00));
16520     }
16521 
16522     //////////
16523     // CBOR //
16524     //////////
16525 
16526     static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16527     {
16528         return to_char_type(0xFA);  // Single-Precision Float
16529     }
16530 
16531     static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16532     {
16533         return to_char_type(0xFB);  // Double-Precision Float
16534     }
16535 
16536     /////////////
16537     // MsgPack //
16538     /////////////
16539 
16540     static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16541     {
16542         return to_char_type(0xCA);  // float 32
16543     }
16544 
16545     static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16546     {
16547         return to_char_type(0xCB);  // float 64
16548     }
16549 
16550     ////////////
16551     // UBJSON //
16552     ////////////
16553 
16554     // UBJSON: write number (floating point)
16555     template<typename NumberType, typename std::enable_if<
16556                  std::is_floating_point<NumberType>::value, int>::type = 0>
16557     void write_number_with_ubjson_prefix(const NumberType n,
16558                                          const bool add_prefix,
16559                                          const bool use_bjdata)
16560     {
16561         if (add_prefix)
16562         {
16563             oa->write_character(get_ubjson_float_prefix(n));
16564         }
16565         write_number(n, use_bjdata);
16566     }
16567 
16568     // UBJSON: write number (unsigned integer)
16569     template<typename NumberType, typename std::enable_if<
16570                  std::is_unsigned<NumberType>::value, int>::type = 0>
16571     void write_number_with_ubjson_prefix(const NumberType n,
16572                                          const bool add_prefix,
16573                                          const bool use_bjdata)
16574     {
16575         if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16576         {
16577             if (add_prefix)
16578             {
16579                 oa->write_character(to_char_type('i'));  // int8
16580             }
16581             write_number(static_cast<std::uint8_t>(n), use_bjdata);
16582         }
16583         else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16584         {
16585             if (add_prefix)
16586             {
16587                 oa->write_character(to_char_type('U'));  // uint8
16588             }
16589             write_number(static_cast<std::uint8_t>(n), use_bjdata);
16590         }
16591         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16592         {
16593             if (add_prefix)
16594             {
16595                 oa->write_character(to_char_type('I'));  // int16
16596             }
16597             write_number(static_cast<std::int16_t>(n), use_bjdata);
16598         }
16599         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16600         {
16601             if (add_prefix)
16602             {
16603                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
16604             }
16605             write_number(static_cast<std::uint16_t>(n), use_bjdata);
16606         }
16607         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16608         {
16609             if (add_prefix)
16610             {
16611                 oa->write_character(to_char_type('l'));  // int32
16612             }
16613             write_number(static_cast<std::int32_t>(n), use_bjdata);
16614         }
16615         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16616         {
16617             if (add_prefix)
16618             {
16619                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
16620             }
16621             write_number(static_cast<std::uint32_t>(n), use_bjdata);
16622         }
16623         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16624         {
16625             if (add_prefix)
16626             {
16627                 oa->write_character(to_char_type('L'));  // int64
16628             }
16629             write_number(static_cast<std::int64_t>(n), use_bjdata);
16630         }
16631         else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16632         {
16633             if (add_prefix)
16634             {
16635                 oa->write_character(to_char_type('M'));  // uint64 - bjdata only
16636             }
16637             write_number(static_cast<std::uint64_t>(n), use_bjdata);
16638         }
16639         else
16640         {
16641             if (add_prefix)
16642             {
16643                 oa->write_character(to_char_type('H'));  // high-precision number
16644             }
16645 
16646             const auto number = BasicJsonType(n).dump();
16647             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16648             for (std::size_t i = 0; i < number.size(); ++i)
16649             {
16650                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16651             }
16652         }
16653     }
16654 
16655     // UBJSON: write number (signed integer)
16656     template < typename NumberType, typename std::enable_if <
16657                    std::is_signed<NumberType>::value&&
16658                    !std::is_floating_point<NumberType>::value, int >::type = 0 >
16659     void write_number_with_ubjson_prefix(const NumberType n,
16660                                          const bool add_prefix,
16661                                          const bool use_bjdata)
16662     {
16663         if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16664         {
16665             if (add_prefix)
16666             {
16667                 oa->write_character(to_char_type('i'));  // int8
16668             }
16669             write_number(static_cast<std::int8_t>(n), use_bjdata);
16670         }
16671         else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
16672         {
16673             if (add_prefix)
16674             {
16675                 oa->write_character(to_char_type('U'));  // uint8
16676             }
16677             write_number(static_cast<std::uint8_t>(n), use_bjdata);
16678         }
16679         else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16680         {
16681             if (add_prefix)
16682             {
16683                 oa->write_character(to_char_type('I'));  // int16
16684             }
16685             write_number(static_cast<std::int16_t>(n), use_bjdata);
16686         }
16687         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
16688         {
16689             if (add_prefix)
16690             {
16691                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
16692             }
16693             write_number(static_cast<uint16_t>(n), use_bjdata);
16694         }
16695         else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16696         {
16697             if (add_prefix)
16698             {
16699                 oa->write_character(to_char_type('l'));  // int32
16700             }
16701             write_number(static_cast<std::int32_t>(n), use_bjdata);
16702         }
16703         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
16704         {
16705             if (add_prefix)
16706             {
16707                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
16708             }
16709             write_number(static_cast<uint32_t>(n), use_bjdata);
16710         }
16711         else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16712         {
16713             if (add_prefix)
16714             {
16715                 oa->write_character(to_char_type('L'));  // int64
16716             }
16717             write_number(static_cast<std::int64_t>(n), use_bjdata);
16718         }
16719         // LCOV_EXCL_START
16720         else
16721         {
16722             if (add_prefix)
16723             {
16724                 oa->write_character(to_char_type('H'));  // high-precision number
16725             }
16726 
16727             const auto number = BasicJsonType(n).dump();
16728             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16729             for (std::size_t i = 0; i < number.size(); ++i)
16730             {
16731                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16732             }
16733         }
16734         // LCOV_EXCL_STOP
16735     }
16736 
16737     /*! 
16738     @brief determine the type prefix of container values 
16739     */
16740     CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16741     {
16742         switch (j.type())
16743         {
16744             case value_t::null:
16745                 return 'Z';
16746 
16747             case value_t::boolean:
16748                 return j.m_data.m_value.boolean ? 'T' : 'F';
16749 
16750             case value_t::number_integer:
16751             {
16752                 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16753                 {
16754                     return 'i';
16755                 }
16756                 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16757                 {
16758                     return 'U';
16759                 }
16760                 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16761                 {
16762                     return 'I';
16763                 }
16764                 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16765                 {
16766                     return 'u';
16767                 }
16768                 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16769                 {
16770                     return 'l';
16771                 }
16772                 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16773                 {
16774                     return 'm';
16775                 }
16776                 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16777                 {
16778                     return 'L';
16779                 }
16780                 // anything else is treated as high-precision number
16781                 return 'H'; // LCOV_EXCL_LINE
16782             }
16783 
16784             case value_t::number_unsigned:
16785             {
16786                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16787                 {
16788                     return 'i';
16789                 }
16790                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16791                 {
16792                     return 'U';
16793                 }
16794                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16795                 {
16796                     return 'I';
16797                 }
16798                 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16799                 {
16800                     return 'u';
16801                 }
16802                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16803                 {
16804                     return 'l';
16805                 }
16806                 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16807                 {
16808                     return 'm';
16809                 }
16810                 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16811                 {
16812                     return 'L';
16813                 }
16814                 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16815                 {
16816                     return 'M';
16817                 }
16818                 // anything else is treated as high-precision number
16819                 return 'H'; // LCOV_EXCL_LINE
16820             }
16821 
16822             case value_t::number_float:
16823                 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16824 
16825             case value_t::string:
16826                 return 'S';
16827 
16828             case value_t::array: // fallthrough
16829             case value_t::binary:
16830                 return '[';
16831 
16832             case value_t::object:
16833                 return '{';
16834 
16835             case value_t::discarded:
16836             default:  // discarded values
16837                 return 'N';
16838         }
16839     }
16840 
16841     static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16842     {
16843         return 'd';  // float 32
16844     }
16845 
16846     static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16847     {
16848         return 'D';  // float 64
16849     }
16850 
16851     /*! 
16852     @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid 
16853     */
16854     bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16855     {
16856         std::map<string_t, CharType> bjdtype = {{"uint8", 'U'},  {"int8", 'i'},  {"uint16", 'u'}, {"int16", 'I'},
16857             {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16858         };
16859 
16860         string_t key = "_ArrayType_";
16861         auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16862         if (it == bjdtype.end())
16863         {
16864             return true;
16865         }
16866         CharType dtype = it->second;
16867 
16868         key = "_ArraySize_";
16869         std::size_t len = (value.at(key).empty() ? 0 : 1);
16870         for (const auto& el : value.at(key))
16871         {
16872             len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16873         }
16874 
16875         key = "_ArrayData_";
16876         if (value.at(key).size() != len)
16877         {
16878             return true;
16879         }
16880 
16881         oa->write_character('[');
16882         oa->write_character('$');
16883         oa->write_character(dtype);
16884         oa->write_character('#');
16885 
16886         key = "_ArraySize_";
16887         write_ubjson(value.at(key), use_count, use_type, true,  true);
16888 
16889         key = "_ArrayData_";
16890         if (dtype == 'U' || dtype == 'C')
16891         {
16892             for (const auto& el : value.at(key))
16893             {
16894                 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16895             }
16896         }
16897         else if (dtype == 'i')
16898         {
16899             for (const auto& el : value.at(key))
16900             {
16901                 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16902             }
16903         }
16904         else if (dtype == 'u')
16905         {
16906             for (const auto& el : value.at(key))
16907             {
16908                 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16909             }
16910         }
16911         else if (dtype == 'I')
16912         {
16913             for (const auto& el : value.at(key))
16914             {
16915                 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16916             }
16917         }
16918         else if (dtype == 'm')
16919         {
16920             for (const auto& el : value.at(key))
16921             {
16922                 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16923             }
16924         }
16925         else if (dtype == 'l')
16926         {
16927             for (const auto& el : value.at(key))
16928             {
16929                 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16930             }
16931         }
16932         else if (dtype == 'M')
16933         {
16934             for (const auto& el : value.at(key))
16935             {
16936                 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16937             }
16938         }
16939         else if (dtype == 'L')
16940         {
16941             for (const auto& el : value.at(key))
16942             {
16943                 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16944             }
16945         }
16946         else if (dtype == 'd')
16947         {
16948             for (const auto& el : value.at(key))
16949             {
16950                 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16951             }
16952         }
16953         else if (dtype == 'D')
16954         {
16955             for (const auto& el : value.at(key))
16956             {
16957                 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16958             }
16959         }
16960         return false;
16961     }
16962 
16963     ///////////////////////
16964     // Utility functions //
16965     ///////////////////////
16966 
16967     /* 
16968     @brief write a number to output input 
16969     @param[in] n number of type @a NumberType 
16970     @param[in] OutputIsLittleEndian Set to true if output data is 
16971                                  required to be little endian 
16972     @tparam NumberType the type of the number 
16973  
16974     @note This function needs to respect the system's endianness, because bytes 
16975           in CBOR, MessagePack, and UBJSON are stored in network order (big 
16976           endian) and therefore need reordering on little endian systems. 
16977           On the other hand, BSON and BJData use little endian and should reorder 
16978           on big endian systems. 
16979     */
16980     template<typename NumberType>
16981     void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16982     {
16983         // step 1: write number to array of length NumberType
16984         std::array<CharType, sizeof(NumberType)> vec{};
16985         std::memcpy(vec.data(), &n, sizeof(NumberType));
16986 
16987         // step 2: write array to output (with possible reordering)
16988         if (is_little_endian != OutputIsLittleEndian)
16989         {
16990             // reverse byte order prior to conversion if necessary
16991             std::reverse(vec.begin(), vec.end());
16992         }
16993 
16994         oa->write_characters(vec.data(), sizeof(NumberType));
16995     }
16996 
16997     void write_compact_float(const number_float_t n, detail::input_format_t format)
16998     {
16999 #ifdef __GNUC__
17000 #pragma GCC diagnostic push
17001 #pragma GCC diagnostic ignored "-Wfloat-equal"
17002 #endif
17003         if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17004                 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17005                 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
17006         {
17007             oa->write_character(format == detail::input_format_t::cbor
17008                                 ? get_cbor_float_prefix(static_cast<float>(n))
17009                                 : get_msgpack_float_prefix(static_cast<float>(n)));
17010             write_number(static_cast<float>(n));
17011         }
17012         else
17013         {
17014             oa->write_character(format == detail::input_format_t::cbor
17015                                 ? get_cbor_float_prefix(n)
17016                                 : get_msgpack_float_prefix(n));
17017             write_number(n);
17018         }
17019 #ifdef __GNUC__
17020 #pragma GCC diagnostic pop
17021 #endif
17022     }
17023 
17024   public:
17025     // The following to_char_type functions are implement the conversion
17026     // between uint8_t and CharType. In case CharType is not unsigned,
17027     // such a conversion is required to allow values greater than 128.
17028     // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17029     template < typename C = CharType,
17030                enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17031     static constexpr CharType to_char_type(std::uint8_t x) noexcept
17032     {
17033         return *reinterpret_cast<char*>(&x);
17034     }
17035 
17036     template < typename C = CharType,
17037                enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17038     static CharType to_char_type(std::uint8_t x) noexcept
17039     {
17040         static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17041         static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17042         CharType result;
17043         std::memcpy(&result, &x, sizeof(x));
17044         return result;
17045     }
17046 
17047     template<typename C = CharType,
17048              enable_if_t<std::is_unsigned<C>::value>* = nullptr>
17049     static constexpr CharType to_char_type(std::uint8_t x) noexcept
17050     {
17051         return x;
17052     }
17053 
17054     template < typename InputCharType, typename C = CharType,
17055                enable_if_t <
17056                    std::is_signed<C>::value &&
17057                    std::is_signed<char>::value &&
17058                    std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17059                    > * = nullptr >
17060     static constexpr CharType to_char_type(InputCharType x) noexcept
17061     {
17062         return x;
17063     }
17064 
17065   private:
17066     /// whether we can assume little endianness
17067     const bool is_little_endian = little_endianness();
17068 
17069     /// the output
17070     output_adapter_t<CharType> oa = nullptr;
17071 };
17072 
17073 }  // namespace detail
17074 NLOHMANN_JSON_NAMESPACE_END
17075 
17076 // #include <nlohmann/detail/output/output_adapters.hpp>
17077 
17078 // #include <nlohmann/detail/output/serializer.hpp>
17079 //     __ _____ _____ _____
17080 //  __|  |   __|     |   | |  JSON for Modern C++
17081 // |  |  |__   |  |  | | | |  version 3.11.3
17082 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
17083 //
17084 // SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17085 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
17086 // SPDX-License-Identifier: MIT
17087 
17088 
17089 
17090 #include <algorithm> // reverse, remove, fill, find, none_of
17091 #include <array> // array
17092 #include <clocale> // localeconv, lconv
17093 #include <cmath> // labs, isfinite, isnan, signbit
17094 #include <cstddef> // size_t, ptrdiff_t
17095 #include <cstdint> // uint8_t
17096 #include <cstdio> // snprintf
17097 #include <limits> // numeric_limits
17098 #include <string> // string, char_traits
17099 #include <iomanip> // setfill, setw
17100 #include <type_traits> // is_same
17101 #include <utility> // move
17102 
17103 // #include <nlohmann/detail/conversions/to_chars.hpp>
17104 //     __ _____ _____ _____
17105 //  __|  |   __|     |   | |  JSON for Modern C++
17106 // |  |  |__   |  |  | | | |  version 3.11.3
17107 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
17108 //
17109 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17110 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
17111 // SPDX-License-Identifier: MIT
17112 
17113 
17114 
17115 #include <array> // array
17116 #include <cmath>   // signbit, isfinite
17117 #include <cstdint> // intN_t, uintN_t
17118 #include <cstring> // memcpy, memmove
17119 #include <limits> // numeric_limits
17120 #include <type_traits> // conditional
17121 
17122 // #include <nlohmann/detail/macro_scope.hpp>
17123 
17124 
17125 NLOHMANN_JSON_NAMESPACE_BEGIN
17126 namespace detail
17127 {
17128 
17129 /*! 
17130 @brief implements the Grisu2 algorithm for binary to decimal floating-point 
17131 conversion. 
17132  
17133 This implementation is a slightly modified version of the reference 
17134 implementation which may be obtained from 
17135 http://florian.loitsch.com/publications (bench.tar.gz). 
17136  
17137 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. 
17138  
17139 For a detailed description of the algorithm see: 
17140  
17141 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with 
17142     Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming 
17143     Language Design and Implementation, PLDI 2010 
17144 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", 
17145     Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language 
17146     Design and Implementation, PLDI 1996 
17147 */
17148 namespace dtoa_impl
17149 {
17150 
17151 template<typename Target, typename Source>
17152 Target reinterpret_bits(const Source source)
17153 {
17154     static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17155 
17156     Target target;
17157     std::memcpy(&target, &source, sizeof(Source));
17158     return target;
17159 }
17160 
17161 struct diyfp // f * 2^e
17162 {
17163     static constexpr int kPrecision = 64; // = q
17164 
17165     std::uint64_t f = 0;
17166     int e = 0;
17167 
17168     constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17169 
17170     /*! 
17171     @brief returns x - y 
17172     @pre x.e == y.e and x.f >= y.f 
17173     */
17174     static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17175     {
17176         JSON_ASSERT(x.e == y.e);
17177         JSON_ASSERT(x.f >= y.f);
17178 
17179         return {x.f - y.f, x.e};
17180     }
17181 
17182     /*! 
17183     @brief returns x * y 
17184     @note The result is rounded. (Only the upper q bits are returned.) 
17185     */
17186     static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17187     {
17188         static_assert(kPrecision == 64, "internal error");
17189 
17190         // Computes:
17191         //  f = round((x.f * y.f) / 2^q)
17192         //  e = x.e + y.e + q
17193 
17194         // Emulate the 64-bit * 64-bit multiplication:
17195         //
17196         // p = u * v
17197         //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17198         //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
17199         //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
17200         //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
17201         //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
17202         //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
17203         //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
17204         //
17205         // (Since Q might be larger than 2^32 - 1)
17206         //
17207         //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17208         //
17209         // (Q_hi + H does not overflow a 64-bit int)
17210         //
17211         //   = p_lo + 2^64 p_hi
17212 
17213         const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17214         const std::uint64_t u_hi = x.f >> 32u;
17215         const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17216         const std::uint64_t v_hi = y.f >> 32u;
17217 
17218         const std::uint64_t p0 = u_lo * v_lo;
17219         const std::uint64_t p1 = u_lo * v_hi;
17220         const std::uint64_t p2 = u_hi * v_lo;
17221         const std::uint64_t p3 = u_hi * v_hi;
17222 
17223         const std::uint64_t p0_hi = p0 >> 32u;
17224         const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17225         const std::uint64_t p1_hi = p1 >> 32u;
17226         const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17227         const std::uint64_t p2_hi = p2 >> 32u;
17228 
17229         std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17230 
17231         // The full product might now be computed as
17232         //
17233         // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17234         // p_lo = p0_lo + (Q << 32)
17235         //
17236         // But in this particular case here, the full p_lo is not required.
17237         // Effectively we only need to add the highest bit in p_lo to p_hi (and
17238         // Q_hi + 1 does not overflow).
17239 
17240         Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17241 
17242         const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17243 
17244         return {h, x.e + y.e + 64};
17245     }
17246 
17247     /*! 
17248     @brief normalize x such that the significand is >= 2^(q-1) 
17249     @pre x.f != 0 
17250     */
17251     static diyfp normalize(diyfp x) noexcept
17252     {
17253         JSON_ASSERT(x.f != 0);
17254 
17255         while ((x.f >> 63u) == 0)
17256         {
17257             x.f <<= 1u;
17258             x.e--;
17259         }
17260 
17261         return x;
17262     }
17263 
17264     /*! 
17265     @brief normalize x such that the result has the exponent E 
17266     @pre e >= x.e and the upper e - x.e bits of x.f must be zero. 
17267     */
17268     static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17269     {
17270         const int delta = x.e - target_exponent;
17271 
17272         JSON_ASSERT(delta >= 0);
17273         JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17274 
17275         return {x.f << delta, target_exponent};
17276     }
17277 };
17278 
17279 struct boundaries
17280 {
17281     diyfp w;
17282     diyfp minus;
17283     diyfp plus;
17284 };
17285 
17286 /*! 
17287 Compute the (normalized) diyfp representing the input number 'value' and its 
17288 boundaries. 
17289  
17290 @pre value must be finite and positive 
17291 */
17292 template<typename FloatType>
17293 boundaries compute_boundaries(FloatType value)
17294 {
17295     JSON_ASSERT(std::isfinite(value));
17296     JSON_ASSERT(value > 0);
17297 
17298     // Convert the IEEE representation into a diyfp.
17299     //
17300     // If v is denormal:
17301     //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
17302     // If v is normalized:
17303     //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17304 
17305     static_assert(std::numeric_limits<FloatType>::is_iec559,
17306                   "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17307 
17308     constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17309     constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17310     constexpr int      kMinExp    = 1 - kBias;
17311     constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17312 
17313     using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17314 
17315     const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17316     const std::uint64_t E = bits >> (kPrecision - 1);
17317     const std::uint64_t F = bits & (kHiddenBit - 1);
17318 
17319     const bool is_denormal = E == 0;
17320     const diyfp v = is_denormal
17321                     ? diyfp(F, kMinExp)
17322                     : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17323 
17324     // Compute the boundaries m- and m+ of the floating-point value
17325     // v = f * 2^e.
17326     //
17327     // Determine v- and v+, the floating-point predecessor and successor if v,
17328     // respectively.
17329     //
17330     //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
17331     //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
17332     //
17333     //      v+ = v + 2^e
17334     //
17335     // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17336     // between m- and m+ round to v, regardless of how the input rounding
17337     // algorithm breaks ties.
17338     //
17339     //      ---+-------------+-------------+-------------+-------------+---  (A)
17340     //         v-            m-            v             m+            v+
17341     //
17342     //      -----------------+------+------+-------------+-------------+---  (B)
17343     //                       v-     m-     v             m+            v+
17344 
17345     const bool lower_boundary_is_closer = F == 0 && E > 1;
17346     const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17347     const diyfp m_minus = lower_boundary_is_closer
17348                           ? diyfp((4 * v.f) - 1, v.e - 2)  // (B)
17349                           : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17350 
17351     // Determine the normalized w+ = m+.
17352     const diyfp w_plus = diyfp::normalize(m_plus);
17353 
17354     // Determine w- = m- such that e_(w-) = e_(w+).
17355     const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17356 
17357     return {diyfp::normalize(v), w_minus, w_plus};
17358 }
17359 
17360 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
17361 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17362 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
17363 //
17364 //      alpha <= e = e_c + e_w + q <= gamma
17365 //
17366 // or
17367 //
17368 //      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17369 //                          <= f_c * f_w * 2^gamma
17370 //
17371 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17372 //
17373 //      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17374 //
17375 // or
17376 //
17377 //      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17378 //
17379 // The choice of (alpha,gamma) determines the size of the table and the form of
17380 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17381 // in practice:
17382 //
17383 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
17384 // processed independently: An integral part p1, and a fractional part p2:
17385 //
17386 //      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17387 //              = (f div 2^-e) + (f mod 2^-e) * 2^e
17388 //              = p1 + p2 * 2^e
17389 //
17390 // The conversion of p1 into decimal form requires a series of divisions and
17391 // modulos by (a power of) 10. These operations are faster for 32-bit than for
17392 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17393 // achieved by choosing
17394 //
17395 //      -e >= 32   or   e <= -32 := gamma
17396 //
17397 // In order to convert the fractional part
17398 //
17399 //      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17400 //
17401 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17402 // d[-i] are extracted in order:
17403 //
17404 //      (10 * p2) div 2^-e = d[-1]
17405 //      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17406 //
17407 // The multiplication by 10 must not overflow. It is sufficient to choose
17408 //
17409 //      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17410 //
17411 // Since p2 = f mod 2^-e < 2^-e,
17412 //
17413 //      -e <= 60   or   e >= -60 := alpha
17414 
17415 constexpr int kAlpha = -60;
17416 constexpr int kGamma = -32;
17417 
17418 struct cached_power // c = f * 2^e ~= 10^k
17419 {
17420     std::uint64_t f;
17421     int e;
17422     int k;
17423 };
17424 
17425 /*! 
17426 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached 
17427 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c 
17428 satisfies (Definition 3.2 from [1]) 
17429  
17430      alpha <= e_c + e + q <= gamma. 
17431 */
17432 inline cached_power get_cached_power_for_binary_exponent(int e)
17433 {
17434     // Now
17435     //
17436     //      alpha <= e_c + e + q <= gamma                                    (1)
17437     //      ==> f_c * 2^alpha <= c * 2^e * 2^q
17438     //
17439     // and since the c's are normalized, 2^(q-1) <= f_c,
17440     //
17441     //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17442     //      ==> 2^(alpha - e - 1) <= c
17443     //
17444     // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17445     //
17446     //      k = ceil( log_10( 2^(alpha - e - 1) ) )
17447     //        = ceil( (alpha - e - 1) * log_10(2) )
17448     //
17449     // From the paper:
17450     // "In theory the result of the procedure could be wrong since c is rounded,
17451     //  and the computation itself is approximated [...]. In practice, however,
17452     //  this simple function is sufficient."
17453     //
17454     // For IEEE double precision floating-point numbers converted into
17455     // normalized diyfp's w = f * 2^e, with q = 64,
17456     //
17457     //      e >= -1022      (min IEEE exponent)
17458     //           -52        (p - 1)
17459     //           -52        (p - 1, possibly normalize denormal IEEE numbers)
17460     //           -11        (normalize the diyfp)
17461     //         = -1137
17462     //
17463     // and
17464     //
17465     //      e <= +1023      (max IEEE exponent)
17466     //           -52        (p - 1)
17467     //           -11        (normalize the diyfp)
17468     //         = 960
17469     //
17470     // This binary exponent range [-1137,960] results in a decimal exponent
17471     // range [-307,324]. One does not need to store a cached power for each
17472     // k in this range. For each such k it suffices to find a cached power
17473     // such that the exponent of the product lies in [alpha,gamma].
17474     // This implies that the difference of the decimal exponents of adjacent
17475     // table entries must be less than or equal to
17476     //
17477     //      floor( (gamma - alpha) * log_10(2) ) = 8.
17478     //
17479     // (A smaller distance gamma-alpha would require a larger table.)
17480 
17481     // NB:
17482     // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17483 
17484     constexpr int kCachedPowersMinDecExp = -300;
17485     constexpr int kCachedPowersDecStep = 8;
17486 
17487     static constexpr std::array<cached_power, 79> kCachedPowers =
17488     {
17489         {
17490             { 0xAB70FE17C79AC6CA, -1060, -300 },
17491             { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17492             { 0xBE5691EF416BD60C, -1007, -284 },
17493             { 0x8DD01FAD907FFC3C,  -980, -276 },
17494             { 0xD3515C2831559A83,  -954, -268 },
17495             { 0x9D71AC8FADA6C9B5,  -927, -260 },
17496             { 0xEA9C227723EE8BCB,  -901, -252 },
17497             { 0xAECC49914078536D,  -874, -244 },
17498             { 0x823C12795DB6CE57,  -847, -236 },
17499             { 0xC21094364DFB5637,  -821, -228 },
17500             { 0x9096EA6F3848984F,  -794, -220 },
17501             { 0xD77485CB25823AC7,  -768, -212 },
17502             { 0xA086CFCD97BF97F4,  -741, -204 },
17503             { 0xEF340A98172AACE5,  -715, -196 },
17504             { 0xB23867FB2A35B28E,  -688, -188 },
17505             { 0x84C8D4DFD2C63F3B,  -661, -180 },
17506             { 0xC5DD44271AD3CDBA,  -635, -172 },
17507             { 0x936B9FCEBB25C996,  -608, -164 },
17508             { 0xDBAC6C247D62A584,  -582, -156 },
17509             { 0xA3AB66580D5FDAF6,  -555, -148 },
17510             { 0xF3E2F893DEC3F126,  -529, -140 },
17511             { 0xB5B5ADA8AAFF80B8,  -502, -132 },
17512             { 0x87625F056C7C4A8B,  -475, -124 },
17513             { 0xC9BCFF6034C13053,  -449, -116 },
17514             { 0x964E858C91BA2655,  -422, -108 },
17515             { 0xDFF9772470297EBD,  -396, -100 },
17516             { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
17517             { 0xF8A95FCF88747D94,  -343,  -84 },
17518             { 0xB94470938FA89BCF,  -316,  -76 },
17519             { 0x8A08F0F8BF0F156B,  -289,  -68 },
17520             { 0xCDB02555653131B6,  -263,  -60 },
17521             { 0x993FE2C6D07B7FAC,  -236,  -52 },
17522             { 0xE45C10C42A2B3B06,  -210,  -44 },
17523             { 0xAA242499697392D3,  -183,  -36 },
17524             { 0xFD87B5F28300CA0E,  -157,  -28 },
17525             { 0xBCE5086492111AEB,  -130,  -20 },
17526             { 0x8CBCCC096F5088CC,  -103,  -12 },
17527             { 0xD1B71758E219652C,   -77,   -4 },
17528             { 0x9C40000000000000,   -50,    4 },
17529             { 0xE8D4A51000000000,   -24,   12 },
17530             { 0xAD78EBC5AC620000,     3,   20 },
17531             { 0x813F3978F8940984,    30,   28 },
17532             { 0xC097CE7BC90715B3,    56,   36 },
17533             { 0x8F7E32CE7BEA5C70,    83,   44 },
17534             { 0xD5D238A4ABE98068,   109,   52 },
17535             { 0x9F4F2726179A2245,   136,   60 },
17536             { 0xED63A231D4C4FB27,   162,   68 },
17537             { 0xB0DE65388CC8ADA8,   189,   76 },
17538             { 0x83C7088E1AAB65DB,   216,   84 },
17539             { 0xC45D1DF942711D9A,   242,   92 },
17540             { 0x924D692CA61BE758,   269,  100 },
17541             { 0xDA01EE641A708DEA,   295,  108 },
17542             { 0xA26DA3999AEF774A,   322,  116 },
17543             { 0xF209787BB47D6B85,   348,  124 },
17544             { 0xB454E4A179DD1877,   375,  132 },
17545             { 0x865B86925B9BC5C2,   402,  140 },
17546             { 0xC83553C5C8965D3D,   428,  148 },
17547             { 0x952AB45CFA97A0B3,   455,  156 },
17548             { 0xDE469FBD99A05FE3,   481,  164 },
17549             { 0xA59BC234DB398C25,   508,  172 },
17550             { 0xF6C69A72A3989F5C,   534,  180 },
17551             { 0xB7DCBF5354E9BECE,   561,  188 },
17552             { 0x88FCF317F22241E2,   588,  196 },
17553             { 0xCC20CE9BD35C78A5,   614,  204 },
17554             { 0x98165AF37B2153DF,   641,  212 },
17555             { 0xE2A0B5DC971F303A,   667,  220 },
17556             { 0xA8D9D1535CE3B396,   694,  228 },
17557             { 0xFB9B7CD9A4A7443C,   720,  236 },
17558             { 0xBB764C4CA7A44410,   747,  244 },
17559             { 0x8BAB8EEFB6409C1A,   774,  252 },
17560             { 0xD01FEF10A657842C,   800,  260 },
17561             { 0x9B10A4E5E9913129,   827,  268 },
17562             { 0xE7109BFBA19C0C9D,   853,  276 },
17563             { 0xAC2820D9623BF429,   880,  284 },
17564             { 0x80444B5E7AA7CF85,   907,  292 },
17565             { 0xBF21E44003ACDD2D,   933,  300 },
17566             { 0x8E679C2F5E44FF8F,   960,  308 },
17567             { 0xD433179D9C8CB841,   986,  316 },
17568             { 0x9E19DB92B4E31BA9,  1013,  324 },
17569         }
17570     };
17571 
17572     // This computation gives exactly the same results for k as
17573     //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17574     // for |e| <= 1500, but doesn't require floating-point operations.
17575     // NB: log_10(2) ~= 78913 / 2^18
17576     JSON_ASSERT(e >= -1500);
17577     JSON_ASSERT(e <=  1500);
17578     const int f = kAlpha - e - 1;
17579     const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
17580 
17581     const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17582     JSON_ASSERT(index >= 0);
17583     JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17584 
17585     const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17586     JSON_ASSERT(kAlpha <= cached.e + e + 64);
17587     JSON_ASSERT(kGamma >= cached.e + e + 64);
17588 
17589     return cached;
17590 }
17591 
17592 /*! 
17593 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. 
17594 For n == 0, returns 1 and sets pow10 := 1. 
17595 */
17596 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17597 {
17598     // LCOV_EXCL_START
17599     if (n >= 1000000000)
17600     {
17601         pow10 = 1000000000;
17602         return 10;
17603     }
17604     // LCOV_EXCL_STOP
17605     if (n >= 100000000)
17606     {
17607         pow10 = 100000000;
17608         return  9;
17609     }
17610     if (n >= 10000000)
17611     {
17612         pow10 = 10000000;
17613         return  8;
17614     }
17615     if (n >= 1000000)
17616     {
17617         pow10 = 1000000;
17618         return  7;
17619     }
17620     if (n >= 100000)
17621     {
17622         pow10 = 100000;
17623         return  6;
17624     }
17625     if (n >= 10000)
17626     {
17627         pow10 = 10000;
17628         return  5;
17629     }
17630     if (n >= 1000)
17631     {
17632         pow10 = 1000;
17633         return  4;
17634     }
17635     if (n >= 100)
17636     {
17637         pow10 = 100;
17638         return  3;
17639     }
17640     if (n >= 10)
17641     {
17642         pow10 = 10;
17643         return  2;
17644     }
17645 
17646     pow10 = 1;
17647     return 1;
17648 }
17649 
17650 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17651                          std::uint64_t rest, std::uint64_t ten_k)
17652 {
17653     JSON_ASSERT(len >= 1);
17654     JSON_ASSERT(dist <= delta);
17655     JSON_ASSERT(rest <= delta);
17656     JSON_ASSERT(ten_k > 0);
17657 
17658     //               <--------------------------- delta ---->
17659     //                                  <---- dist --------->
17660     // --------------[------------------+-------------------]--------------
17661     //               M-                 w                   M+
17662     //
17663     //                                  ten_k
17664     //                                <------>
17665     //                                       <---- rest ---->
17666     // --------------[------------------+----+--------------]--------------
17667     //                                  w    V
17668     //                                       = buf * 10^k
17669     //
17670     // ten_k represents a unit-in-the-last-place in the decimal representation
17671     // stored in buf.
17672     // Decrement buf by ten_k while this takes buf closer to w.
17673 
17674     // The tests are written in this order to avoid overflow in unsigned
17675     // integer arithmetic.
17676 
17677     while (rest < dist
17678             && delta - rest >= ten_k
17679             && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17680     {
17681         JSON_ASSERT(buf[len - 1] != '0');
17682         buf[len - 1]--;
17683         rest += ten_k;
17684     }
17685 }
17686 
17687 /*! 
17688 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. 
17689 M- and M+ must be normalized and share the same exponent -60 <= e <= -32. 
17690 */
17691 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17692                              diyfp M_minus, diyfp w, diyfp M_plus)
17693 {
17694     static_assert(kAlpha >= -60, "internal error");
17695     static_assert(kGamma <= -32, "internal error");
17696 
17697     // Generates the digits (and the exponent) of a decimal floating-point
17698     // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17699     // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17700     //
17701     //               <--------------------------- delta ---->
17702     //                                  <---- dist --------->
17703     // --------------[------------------+-------------------]--------------
17704     //               M-                 w                   M+
17705     //
17706     // Grisu2 generates the digits of M+ from left to right and stops as soon as
17707     // V is in [M-,M+].
17708 
17709     JSON_ASSERT(M_plus.e >= kAlpha);
17710     JSON_ASSERT(M_plus.e <= kGamma);
17711 
17712     std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17713     std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
17714 
17715     // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17716     //
17717     //      M+ = f * 2^e
17718     //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17719     //         = ((p1        ) * 2^-e + (p2        )) * 2^e
17720     //         = p1 + p2 * 2^e
17721 
17722     const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17723 
17724     auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
17725     std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
17726 
17727     // 1)
17728     //
17729     // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17730 
17731     JSON_ASSERT(p1 > 0);
17732 
17733     std::uint32_t pow10{};
17734     const int k = find_largest_pow10(p1, pow10);
17735 
17736     //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17737     //
17738     //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17739     //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
17740     //
17741     //      M+ = p1                                             + p2 * 2^e
17742     //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
17743     //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17744     //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
17745     //
17746     // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17747     //
17748     //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17749     //
17750     // but stop as soon as
17751     //
17752     //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17753 
17754     int n = k;
17755     while (n > 0)
17756     {
17757         // Invariants:
17758         //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
17759         //      pow10 = 10^(n-1) <= p1 < 10^n
17760         //
17761         const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
17762         const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
17763         //
17764         //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17765         //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17766         //
17767         JSON_ASSERT(d <= 9);
17768         buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17769         //
17770         //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17771         //
17772         p1 = r;
17773         n--;
17774         //
17775         //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
17776         //      pow10 = 10^n
17777         //
17778 
17779         // Now check if enough digits have been generated.
17780         // Compute
17781         //
17782         //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17783         //
17784         // Note:
17785         // Since rest and delta share the same exponent e, it suffices to
17786         // compare the significands.
17787         const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17788         if (rest <= delta)
17789         {
17790             // V = buffer * 10^n, with M- <= V <= M+.
17791 
17792             decimal_exponent += n;
17793 
17794             // We may now just stop. But instead look if the buffer could be
17795             // decremented to bring V closer to w.
17796             //
17797             // pow10 = 10^n is now 1 ulp in the decimal representation V.
17798             // The rounding procedure works with diyfp's with an implicit
17799             // exponent of e.
17800             //
17801             //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17802             //
17803             const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17804             grisu2_round(buffer, length, dist, delta, rest, ten_n);
17805 
17806             return;
17807         }
17808 
17809         pow10 /= 10;
17810         //
17811         //      pow10 = 10^(n-1) <= p1 < 10^n
17812         // Invariants restored.
17813     }
17814 
17815     // 2)
17816     //
17817     // The digits of the integral part have been generated:
17818     //
17819     //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17820     //         = buffer            + p2 * 2^e
17821     //
17822     // Now generate the digits of the fractional part p2 * 2^e.
17823     //
17824     // Note:
17825     // No decimal point is generated: the exponent is adjusted instead.
17826     //
17827     // p2 actually represents the fraction
17828     //
17829     //      p2 * 2^e
17830     //          = p2 / 2^-e
17831     //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
17832     //
17833     // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17834     //
17835     //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17836     //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17837     //
17838     // using
17839     //
17840     //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17841     //                = (                   d) * 2^-e + (                   r)
17842     //
17843     // or
17844     //      10^m * p2 * 2^e = d + r * 2^e
17845     //
17846     // i.e.
17847     //
17848     //      M+ = buffer + p2 * 2^e
17849     //         = buffer + 10^-m * (d + r * 2^e)
17850     //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17851     //
17852     // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17853 
17854     JSON_ASSERT(p2 > delta);
17855 
17856     int m = 0;
17857     for (;;)
17858     {
17859         // Invariant:
17860         //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17861         //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
17862         //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
17863         //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17864         //
17865         JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17866         p2 *= 10;
17867         const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
17868         const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17869         //
17870         //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17871         //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17872         //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17873         //
17874         JSON_ASSERT(d <= 9);
17875         buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17876         //
17877         //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17878         //
17879         p2 = r;
17880         m++;
17881         //
17882         //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17883         // Invariant restored.
17884 
17885         // Check if enough digits have been generated.
17886         //
17887         //      10^-m * p2 * 2^e <= delta * 2^e
17888         //              p2 * 2^e <= 10^m * delta * 2^e
17889         //                    p2 <= 10^m * delta
17890         delta *= 10;
17891         dist  *= 10;
17892         if (p2 <= delta)
17893         {
17894             break;
17895         }
17896     }
17897 
17898     // V = buffer * 10^-m, with M- <= V <= M+.
17899 
17900     decimal_exponent -= m;
17901 
17902     // 1 ulp in the decimal representation is now 10^-m.
17903     // Since delta and dist are now scaled by 10^m, we need to do the
17904     // same with ulp in order to keep the units in sync.
17905     //
17906     //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17907     //
17908     const std::uint64_t ten_m = one.f;
17909     grisu2_round(buffer, length, dist, delta, p2, ten_m);
17910 
17911     // By construction this algorithm generates the shortest possible decimal
17912     // number (Loitsch, Theorem 6.2) which rounds back to w.
17913     // For an input number of precision p, at least
17914     //
17915     //      N = 1 + ceil(p * log_10(2))
17916     //
17917     // decimal digits are sufficient to identify all binary floating-point
17918     // numbers (Matula, "In-and-Out conversions").
17919     // This implies that the algorithm does not produce more than N decimal
17920     // digits.
17921     //
17922     //      N = 17 for p = 53 (IEEE double precision)
17923     //      N = 9  for p = 24 (IEEE single precision)
17924 }
17925 
17926 /*! 
17927 v = buf * 10^decimal_exponent 
17928 len is the length of the buffer (number of decimal digits) 
17929 The buffer must be large enough, i.e. >= max_digits10. 
17930 */
17931 JSON_HEDLEY_NON_NULL(1)
17932 inline void grisu2(char* buf, int& len, int& decimal_exponent,
17933                    diyfp m_minus, diyfp v, diyfp m_plus)
17934 {
17935     JSON_ASSERT(m_plus.e == m_minus.e);
17936     JSON_ASSERT(m_plus.e == v.e);
17937 
17938     //  --------(-----------------------+-----------------------)--------    (A)
17939     //          m-                      v                       m+
17940     //
17941     //  --------------------(-----------+-----------------------)--------    (B)
17942     //                      m-          v                       m+
17943     //
17944     // First scale v (and m- and m+) such that the exponent is in the range
17945     // [alpha, gamma].
17946 
17947     const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17948 
17949     const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17950 
17951     // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17952     const diyfp w       = diyfp::mul(v,       c_minus_k);
17953     const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17954     const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
17955 
17956     //  ----(---+---)---------------(---+---)---------------(---+---)----
17957     //          w-                      w                       w+
17958     //          = c*m-                  = c*v                   = c*m+
17959     //
17960     // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17961     // w+ are now off by a small amount.
17962     // In fact:
17963     //
17964     //      w - v * 10^k < 1 ulp
17965     //
17966     // To account for this inaccuracy, add resp. subtract 1 ulp.
17967     //
17968     //  --------+---[---------------(---+---)---------------]---+--------
17969     //          w-  M-                  w                   M+  w+
17970     //
17971     // Now any number in [M-, M+] (bounds included) will round to w when input,
17972     // regardless of how the input rounding algorithm breaks ties.
17973     //
17974     // And digit_gen generates the shortest possible such number in [M-, M+].
17975     // Note that this does not mean that Grisu2 always generates the shortest
17976     // possible number in the interval (m-, m+).
17977     const diyfp M_minus(w_minus.f + 1, w_minus.e);
17978     const diyfp M_plus (w_plus.f  - 1, w_plus.e );
17979 
17980     decimal_exponent = -cached.k; // = -(-k) = k
17981 
17982     grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17983 }
17984 
17985 /*! 
17986 v = buf * 10^decimal_exponent 
17987 len is the length of the buffer (number of decimal digits) 
17988 The buffer must be large enough, i.e. >= max_digits10. 
17989 */
17990 template<typename FloatType>
17991 JSON_HEDLEY_NON_NULL(1)
17992 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17993 {
17994     static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17995                   "internal error: not enough precision");
17996 
17997     JSON_ASSERT(std::isfinite(value));
17998     JSON_ASSERT(value > 0);
17999 
18000     // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18001     // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18002     // decimal representations are not exactly "short".
18003     //
18004     // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18005     // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18006     // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18007     // does.
18008     // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18009     // representation using the corresponding std::from_chars function recovers value exactly". That
18010     // indicates that single precision floating-point numbers should be recovered using
18011     // 'std::strtof'.
18012     //
18013     // NB: If the neighbors are computed for single-precision numbers, there is a single float
18014     //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18015     //     value is off by 1 ulp.
18016 #if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18017     const boundaries w = compute_boundaries(static_cast<double>(value));
18018 #else
18019     const boundaries w = compute_boundaries(value);
18020 #endif
18021 
18022     grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18023 }
18024 
18025 /*! 
18026 @brief appends a decimal representation of e to buf 
18027 @return a pointer to the element following the exponent. 
18028 @pre -1000 < e < 1000 
18029 */
18030 JSON_HEDLEY_NON_NULL(1)
18031 JSON_HEDLEY_RETURNS_NON_NULL
18032 inline char* append_exponent(char* buf, int e)
18033 {
18034     JSON_ASSERT(e > -1000);
18035     JSON_ASSERT(e <  1000);
18036 
18037     if (e < 0)
18038     {
18039         e = -e;
18040         *buf++ = '-';
18041     }
18042     else
18043     {
18044         *buf++ = '+';
18045     }
18046 
18047     auto k = static_cast<std::uint32_t>(e);
18048     if (k < 10)
18049     {
18050         // Always print at least two digits in the exponent.
18051         // This is for compatibility with printf("%g").
18052         *buf++ = '0';
18053         *buf++ = static_cast<char>('0' + k);
18054     }
18055     else if (k < 100)
18056     {
18057         *buf++ = static_cast<char>('0' + (k / 10));
18058         k %= 10;
18059         *buf++ = static_cast<char>('0' + k);
18060     }
18061     else
18062     {
18063         *buf++ = static_cast<char>('0' + (k / 100));
18064         k %= 100;
18065         *buf++ = static_cast<char>('0' + (k / 10));
18066         k %= 10;
18067         *buf++ = static_cast<char>('0' + k);
18068     }
18069 
18070     return buf;
18071 }
18072 
18073 /*! 
18074 @brief prettify v = buf * 10^decimal_exponent 
18075  
18076 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point 
18077 notation. Otherwise it will be printed in exponential notation. 
18078  
18079 @pre min_exp < 0 
18080 @pre max_exp > 0 
18081 */
18082 JSON_HEDLEY_NON_NULL(1)
18083 JSON_HEDLEY_RETURNS_NON_NULL
18084 inline char* format_buffer(char* buf, int len, int decimal_exponent,
18085                            int min_exp, int max_exp)
18086 {
18087     JSON_ASSERT(min_exp < 0);
18088     JSON_ASSERT(max_exp > 0);
18089 
18090     const int k = len;
18091     const int n = len + decimal_exponent;
18092 
18093     // v = buf * 10^(n-k)
18094     // k is the length of the buffer (number of decimal digits)
18095     // n is the position of the decimal point relative to the start of the buffer.
18096 
18097     if (k <= n && n <= max_exp)
18098     {
18099         // digits[000]
18100         // len <= max_exp + 2
18101 
18102         std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18103         // Make it look like a floating-point number (#362, #378)
18104         buf[n + 0] = '.';
18105         buf[n + 1] = '0';
18106         return buf + (static_cast<size_t>(n) + 2);
18107     }
18108 
18109     if (0 < n && n <= max_exp)
18110     {
18111         // dig.its
18112         // len <= max_digits10 + 1
18113 
18114         JSON_ASSERT(k > n);
18115 
18116         std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18117         buf[n] = '.';
18118         return buf + (static_cast<size_t>(k) + 1U);
18119     }
18120 
18121     if (min_exp < n && n <= 0)
18122     {
18123         // 0.[000]digits
18124         // len <= 2 + (-min_exp - 1) + max_digits10
18125 
18126         std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18127         buf[0] = '0';
18128         buf[1] = '.';
18129         std::memset(buf + 2, '0', static_cast<size_t>(-n));
18130         return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18131     }
18132 
18133     if (k == 1)
18134     {
18135         // dE+123
18136         // len <= 1 + 5
18137 
18138         buf += 1;
18139     }
18140     else
18141     {
18142         // d.igitsE+123
18143         // len <= max_digits10 + 1 + 5
18144 
18145         std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18146         buf[1] = '.';
18147         buf += 1 + static_cast<size_t>(k);
18148     }
18149 
18150     *buf++ = 'e';
18151     return append_exponent(buf, n - 1);
18152 }
18153 
18154 }  // namespace dtoa_impl
18155 
18156 /*! 
18157 @brief generates a decimal representation of the floating-point number value in [first, last). 
18158  
18159 The format of the resulting decimal representation is similar to printf's %g 
18160 format. Returns an iterator pointing past-the-end of the decimal representation. 
18161  
18162 @note The input number must be finite, i.e. NaN's and Inf's are not supported. 
18163 @note The buffer must be large enough. 
18164 @note The result is NOT null-terminated. 
18165 */
18166 template<typename FloatType>
18167 JSON_HEDLEY_NON_NULL(1, 2)
18168 JSON_HEDLEY_RETURNS_NON_NULL
18169 char* to_chars(char* first, const char* last, FloatType value)
18170 {
18171     static_cast<void>(last); // maybe unused - fix warning
18172     JSON_ASSERT(std::isfinite(value));
18173 
18174     // Use signbit(value) instead of (value < 0) since signbit works for -0.
18175     if (std::signbit(value))
18176     {
18177         value = -value;
18178         *first++ = '-';
18179     }
18180 
18181 #ifdef __GNUC__
18182 #pragma GCC diagnostic push
18183 #pragma GCC diagnostic ignored "-Wfloat-equal"
18184 #endif
18185     if (value == 0) // +-0
18186     {
18187         *first++ = '0';
18188         // Make it look like a floating-point number (#362, #378)
18189         *first++ = '.';
18190         *first++ = '0';
18191         return first;
18192     }
18193 #ifdef __GNUC__
18194 #pragma GCC diagnostic pop
18195 #endif
18196 
18197     JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18198 
18199     // Compute v = buffer * 10^decimal_exponent.
18200     // The decimal digits are stored in the buffer, which needs to be interpreted
18201     // as an unsigned decimal integer.
18202     // len is the length of the buffer, i.e. the number of decimal digits.
18203     int len = 0;
18204     int decimal_exponent = 0;
18205     dtoa_impl::grisu2(first, len, decimal_exponent, value);
18206 
18207     JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18208 
18209     // Format the buffer like printf("%.*g", prec, value)
18210     constexpr int kMinExp = -4;
18211     // Use digits10 here to increase compatibility with version 2.
18212     constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18213 
18214     JSON_ASSERT(last - first >= kMaxExp + 2);
18215     JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18216     JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18217 
18218     return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18219 }
18220 
18221 }  // namespace detail
18222 NLOHMANN_JSON_NAMESPACE_END
18223 
18224 // #include <nlohmann/detail/exceptions.hpp>
18225 
18226 // #include <nlohmann/detail/macro_scope.hpp>
18227 
18228 // #include <nlohmann/detail/meta/cpp_future.hpp>
18229 
18230 // #include <nlohmann/detail/output/binary_writer.hpp>
18231 
18232 // #include <nlohmann/detail/output/output_adapters.hpp>
18233 
18234 // #include <nlohmann/detail/string_concat.hpp>
18235 
18236 // #include <nlohmann/detail/value_t.hpp>
18237 
18238 
18239 NLOHMANN_JSON_NAMESPACE_BEGIN
18240 namespace detail
18241 {
18242 
18243 ///////////////////
18244 // serialization //
18245 ///////////////////
18246 
18247 /// how to treat decoding errors
18248 enum class error_handler_t
18249 {
18250     strict,  ///< throw a type_error exception in case of invalid UTF-8
18251     replace, ///< replace invalid UTF-8 sequences with U+FFFD
18252     ignore   ///< ignore invalid UTF-8 sequences
18253 };
18254 
18255 template<typename BasicJsonType>
18256 class serializer
18257 {
18258     using string_t = typename BasicJsonType::string_t;
18259     using number_float_t = typename BasicJsonType::number_float_t;
18260     using number_integer_t = typename BasicJsonType::number_integer_t;
18261     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18262     using binary_char_t = typename BasicJsonType::binary_t::value_type;
18263     static constexpr std::uint8_t UTF8_ACCEPT = 0;
18264     static constexpr std::uint8_t UTF8_REJECT = 1;
18265 
18266   public:
18267     /*! 
18268     @param[in] s  output stream to serialize to 
18269     @param[in] ichar  indentation character to use 
18270     @param[in] error_handler_  how to react on decoding errors 
18271     */
18272     serializer(output_adapter_t<char> s, const char ichar,
18273                error_handler_t error_handler_ = error_handler_t::strict)
18274         : o(std::move(s))
18275         , loc(std::localeconv())
18276         , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18277         , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18278         , indent_char(ichar)
18279         , indent_string(512, indent_char)
18280         , error_handler(error_handler_)
18281     {}
18282 
18283     // delete because of pointer members
18284     serializer(const serializer&) = delete;
18285     serializer& operator=(const serializer&) = delete;
18286     serializer(serializer&&) = delete;
18287     serializer& operator=(serializer&&) = delete;
18288     ~serializer() = default;
18289 
18290     /*! 
18291     @brief internal implementation of the serialization function 
18292  
18293     This function is called by the public member function dump and organizes 
18294     the serialization internally. The indentation level is propagated as 
18295     additional parameter. In case of arrays and objects, the function is 
18296     called recursively. 
18297  
18298     - strings and object keys are escaped using `escape_string()` 
18299     - integer numbers are converted implicitly via `operator<<` 
18300     - floating-point numbers are converted to a string using `"%g"` format 
18301     - binary values are serialized as objects containing the subtype and the 
18302       byte array 
18303  
18304     @param[in] val               value to serialize 
18305     @param[in] pretty_print      whether the output shall be pretty-printed 
18306     @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters 
18307     in the output are escaped with `\uXXXX` sequences, and the result consists 
18308     of ASCII characters only. 
18309     @param[in] indent_step       the indent level 
18310     @param[in] current_indent    the current indent level (only used internally) 
18311     */
18312     void dump(const BasicJsonType& val,
18313               const bool pretty_print,
18314               const bool ensure_ascii,
18315               const unsigned int indent_step,
18316               const unsigned int current_indent = 0)
18317     {
18318         switch (val.m_data.m_type)
18319         {
18320             case value_t::object:
18321             {
18322                 if (val.m_data.m_value.object->empty())
18323                 {
18324                     o->write_characters("{}", 2);
18325                     return;
18326                 }
18327 
18328                 if (pretty_print)
18329                 {
18330                     o->write_characters("{\n", 2);
18331 
18332                     // variable to hold indentation for recursive calls
18333                     const auto new_indent = current_indent + indent_step;
18334                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18335                     {
18336                         indent_string.resize(indent_string.size() * 2, ' ');
18337                     }
18338 
18339                     // first n-1 elements
18340                     auto i = val.m_data.m_value.object->cbegin();
18341                     for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18342                     {
18343                         o->write_characters(indent_string.c_str(), new_indent);
18344                         o->write_character('\"');
18345                         dump_escaped(i->first, ensure_ascii);
18346                         o->write_characters("\": ", 3);
18347                         dump(i->second, true, ensure_ascii, indent_step, new_indent);
18348                         o->write_characters(",\n", 2);
18349                     }
18350 
18351                     // last element
18352                     JSON_ASSERT(i != val.m_data.m_value.object->cend());
18353                     JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18354                     o->write_characters(indent_string.c_str(), new_indent);
18355                     o->write_character('\"');
18356                     dump_escaped(i->first, ensure_ascii);
18357                     o->write_characters("\": ", 3);
18358                     dump(i->second, true, ensure_ascii, indent_step, new_indent);
18359 
18360                     o->write_character('\n');
18361                     o->write_characters(indent_string.c_str(), current_indent);
18362                     o->write_character('}');
18363                 }
18364                 else
18365                 {
18366                     o->write_character('{');
18367 
18368                     // first n-1 elements
18369                     auto i = val.m_data.m_value.object->cbegin();
18370                     for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18371                     {
18372                         o->write_character('\"');
18373                         dump_escaped(i->first, ensure_ascii);
18374                         o->write_characters("\":", 2);
18375                         dump(i->second, false, ensure_ascii, indent_step, current_indent);
18376                         o->write_character(',');
18377                     }
18378 
18379                     // last element
18380                     JSON_ASSERT(i != val.m_data.m_value.object->cend());
18381                     JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18382                     o->write_character('\"');
18383                     dump_escaped(i->first, ensure_ascii);
18384                     o->write_characters("\":", 2);
18385                     dump(i->second, false, ensure_ascii, indent_step, current_indent);
18386 
18387                     o->write_character('}');
18388                 }
18389 
18390                 return;
18391             }
18392 
18393             case value_t::array:
18394             {
18395                 if (val.m_data.m_value.array->empty())
18396                 {
18397                     o->write_characters("[]", 2);
18398                     return;
18399                 }
18400 
18401                 if (pretty_print)
18402                 {
18403                     o->write_characters("[\n", 2);
18404 
18405                     // variable to hold indentation for recursive calls
18406                     const auto new_indent = current_indent + indent_step;
18407                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18408                     {
18409                         indent_string.resize(indent_string.size() * 2, ' ');
18410                     }
18411 
18412                     // first n-1 elements
18413                     for (auto i = val.m_data.m_value.array->cbegin();
18414                             i != val.m_data.m_value.array->cend() - 1; ++i)
18415                     {
18416                         o->write_characters(indent_string.c_str(), new_indent);
18417                         dump(*i, true, ensure_ascii, indent_step, new_indent);
18418                         o->write_characters(",\n", 2);
18419                     }
18420 
18421                     // last element
18422                     JSON_ASSERT(!val.m_data.m_value.array->empty());
18423                     o->write_characters(indent_string.c_str(), new_indent);
18424                     dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18425 
18426                     o->write_character('\n');
18427                     o->write_characters(indent_string.c_str(), current_indent);
18428                     o->write_character(']');
18429                 }
18430                 else
18431                 {
18432                     o->write_character('[');
18433 
18434                     // first n-1 elements
18435                     for (auto i = val.m_data.m_value.array->cbegin();
18436                             i != val.m_data.m_value.array->cend() - 1; ++i)
18437                     {
18438                         dump(*i, false, ensure_ascii, indent_step, current_indent);
18439                         o->write_character(',');
18440                     }
18441 
18442                     // last element
18443                     JSON_ASSERT(!val.m_data.m_value.array->empty());
18444                     dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18445 
18446                     o->write_character(']');
18447                 }
18448 
18449                 return;
18450             }
18451 
18452             case value_t::string:
18453             {
18454                 o->write_character('\"');
18455                 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18456                 o->write_character('\"');
18457                 return;
18458             }
18459 
18460             case value_t::binary:
18461             {
18462                 if (pretty_print)
18463                 {
18464                     o->write_characters("{\n", 2);
18465 
18466                     // variable to hold indentation for recursive calls
18467                     const auto new_indent = current_indent + indent_step;
18468                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18469                     {
18470                         indent_string.resize(indent_string.size() * 2, ' ');
18471                     }
18472 
18473                     o->write_characters(indent_string.c_str(), new_indent);
18474 
18475                     o->write_characters("\"bytes\": [", 10);
18476 
18477                     if (!val.m_data.m_value.binary->empty())
18478                     {
18479                         for (auto i = val.m_data.m_value.binary->cbegin();
18480                                 i != val.m_data.m_value.binary->cend() - 1; ++i)
18481                         {
18482                             dump_integer(*i);
18483                             o->write_characters(", ", 2);
18484                         }
18485                         dump_integer(val.m_data.m_value.binary->back());
18486                     }
18487 
18488                     o->write_characters("],\n", 3);
18489                     o->write_characters(indent_string.c_str(), new_indent);
18490 
18491                     o->write_characters("\"subtype\": ", 11);
18492                     if (val.m_data.m_value.binary->has_subtype())
18493                     {
18494                         dump_integer(val.m_data.m_value.binary->subtype());
18495                     }
18496                     else
18497                     {
18498                         o->write_characters("null", 4);
18499                     }
18500                     o->write_character('\n');
18501                     o->write_characters(indent_string.c_str(), current_indent);
18502                     o->write_character('}');
18503                 }
18504                 else
18505                 {
18506                     o->write_characters("{\"bytes\":[", 10);
18507 
18508                     if (!val.m_data.m_value.binary->empty())
18509                     {
18510                         for (auto i = val.m_data.m_value.binary->cbegin();
18511                                 i != val.m_data.m_value.binary->cend() - 1; ++i)
18512                         {
18513                             dump_integer(*i);
18514                             o->write_character(',');
18515                         }
18516                         dump_integer(val.m_data.m_value.binary->back());
18517                     }
18518 
18519                     o->write_characters("],\"subtype\":", 12);
18520                     if (val.m_data.m_value.binary->has_subtype())
18521                     {
18522                         dump_integer(val.m_data.m_value.binary->subtype());
18523                         o->write_character('}');
18524                     }
18525                     else
18526                     {
18527                         o->write_characters("null}", 5);
18528                     }
18529                 }
18530                 return;
18531             }
18532 
18533             case value_t::boolean:
18534             {
18535                 if (val.m_data.m_value.boolean)
18536                 {
18537                     o->write_characters("true", 4);
18538                 }
18539                 else
18540                 {
18541                     o->write_characters("false", 5);
18542                 }
18543                 return;
18544             }
18545 
18546             case value_t::number_integer:
18547             {
18548                 dump_integer(val.m_data.m_value.number_integer);
18549                 return;
18550             }
18551 
18552             case value_t::number_unsigned:
18553             {
18554                 dump_integer(val.m_data.m_value.number_unsigned);
18555                 return;
18556             }
18557 
18558             case value_t::number_float:
18559             {
18560                 dump_float(val.m_data.m_value.number_float);
18561                 return;
18562             }
18563 
18564             case value_t::discarded:
18565             {
18566                 o->write_characters("<discarded>", 11);
18567                 return;
18568             }
18569 
18570             case value_t::null:
18571             {
18572                 o->write_characters("null", 4);
18573                 return;
18574             }
18575 
18576             default:            // LCOV_EXCL_LINE
18577                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18578         }
18579     }
18580 
18581   JSON_PRIVATE_UNLESS_TESTED:
18582     /*! 
18583     @brief dump escaped string 
18584  
18585     Escape a string by replacing certain special characters by a sequence of an 
18586     escape character (backslash) and another character and other control 
18587     characters by a sequence of "\u" followed by a four-digit hex 
18588     representation. The escaped string is written to output stream @a o. 
18589  
18590     @param[in] s  the string to escape 
18591     @param[in] ensure_ascii  whether to escape non-ASCII characters with 
18592                              \uXXXX sequences 
18593  
18594     @complexity Linear in the length of string @a s. 
18595     */
18596     void dump_escaped(const string_t& s, const bool ensure_ascii)
18597     {
18598         std::uint32_t codepoint{};
18599         std::uint8_t state = UTF8_ACCEPT;
18600         std::size_t bytes = 0;  // number of bytes written to string_buffer
18601 
18602         // number of bytes written at the point of the last valid byte
18603         std::size_t bytes_after_last_accept = 0;
18604         std::size_t undumped_chars = 0;
18605 
18606         for (std::size_t i = 0; i < s.size(); ++i)
18607         {
18608             const auto byte = static_cast<std::uint8_t>(s[i]);
18609 
18610             switch (decode(state, codepoint, byte))
18611             {
18612                 case UTF8_ACCEPT:  // decode found a new code point
18613                 {
18614                     switch (codepoint)
18615                     {
18616                         case 0x08: // backspace
18617                         {
18618                             string_buffer[bytes++] = '\\';
18619                             string_buffer[bytes++] = 'b';
18620                             break;
18621                         }
18622 
18623                         case 0x09: // horizontal tab
18624                         {
18625                             string_buffer[bytes++] = '\\';
18626                             string_buffer[bytes++] = 't';
18627                             break;
18628                         }
18629 
18630                         case 0x0A: // newline
18631                         {
18632                             string_buffer[bytes++] = '\\';
18633                             string_buffer[bytes++] = 'n';
18634                             break;
18635                         }
18636 
18637                         case 0x0C: // formfeed
18638                         {
18639                             string_buffer[bytes++] = '\\';
18640                             string_buffer[bytes++] = 'f';
18641                             break;
18642                         }
18643 
18644                         case 0x0D: // carriage return
18645                         {
18646                             string_buffer[bytes++] = '\\';
18647                             string_buffer[bytes++] = 'r';
18648                             break;
18649                         }
18650 
18651                         case 0x22: // quotation mark
18652                         {
18653                             string_buffer[bytes++] = '\\';
18654                             string_buffer[bytes++] = '\"';
18655                             break;
18656                         }
18657 
18658                         case 0x5C: // reverse solidus
18659                         {
18660                             string_buffer[bytes++] = '\\';
18661                             string_buffer[bytes++] = '\\';
18662                             break;
18663                         }
18664 
18665                         default:
18666                         {
18667                             // escape control characters (0x00..0x1F) or, if
18668                             // ensure_ascii parameter is used, non-ASCII characters
18669                             if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18670                             {
18671                                 if (codepoint <= 0xFFFF)
18672                                 {
18673                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18674                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18675                                                                       static_cast<std::uint16_t>(codepoint)));
18676                                     bytes += 6;
18677                                 }
18678                                 else
18679                                 {
18680                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18681                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18682                                                                       static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18683                                                                       static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18684                                     bytes += 12;
18685                                 }
18686                             }
18687                             else
18688                             {
18689                                 // copy byte to buffer (all previous bytes
18690                                 // been copied have in default case above)
18691                                 string_buffer[bytes++] = s[i];
18692                             }
18693                             break;
18694                         }
18695                     }
18696 
18697                     // write buffer and reset index; there must be 13 bytes
18698                     // left, as this is the maximal number of bytes to be
18699                     // written ("\uxxxx\uxxxx\0") for one code point
18700                     if (string_buffer.size() - bytes < 13)
18701                     {
18702                         o->write_characters(string_buffer.data(), bytes);
18703                         bytes = 0;
18704                     }
18705 
18706                     // remember the byte position of this accept
18707                     bytes_after_last_accept = bytes;
18708                     undumped_chars = 0;
18709                     break;
18710                 }
18711 
18712                 case UTF8_REJECT:  // decode found invalid UTF-8 byte
18713                 {
18714                     switch (error_handler)
18715                     {
18716                         case error_handler_t::strict:
18717                         {
18718                             JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18719                         }
18720 
18721                         case error_handler_t::ignore:
18722                         case error_handler_t::replace:
18723                         {
18724                             // in case we saw this character the first time, we
18725                             // would like to read it again, because the byte
18726                             // may be OK for itself, but just not OK for the
18727                             // previous sequence
18728                             if (undumped_chars > 0)
18729                             {
18730                                 --i;
18731                             }
18732 
18733                             // reset length buffer to the last accepted index;
18734                             // thus removing/ignoring the invalid characters
18735                             bytes = bytes_after_last_accept;
18736 
18737                             if (error_handler == error_handler_t::replace)
18738                             {
18739                                 // add a replacement character
18740                                 if (ensure_ascii)
18741                                 {
18742                                     string_buffer[bytes++] = '\\';
18743                                     string_buffer[bytes++] = 'u';
18744                                     string_buffer[bytes++] = 'f';
18745                                     string_buffer[bytes++] = 'f';
18746                                     string_buffer[bytes++] = 'f';
18747                                     string_buffer[bytes++] = 'd';
18748                                 }
18749                                 else
18750                                 {
18751                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18752                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18753                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18754                                 }
18755 
18756                                 // write buffer and reset index; there must be 13 bytes
18757                                 // left, as this is the maximal number of bytes to be
18758                                 // written ("\uxxxx\uxxxx\0") for one code point
18759                                 if (string_buffer.size() - bytes < 13)
18760                                 {
18761                                     o->write_characters(string_buffer.data(), bytes);
18762                                     bytes = 0;
18763                                 }
18764 
18765                                 bytes_after_last_accept = bytes;
18766                             }
18767 
18768                             undumped_chars = 0;
18769 
18770                             // continue processing the string
18771                             state = UTF8_ACCEPT;
18772                             break;
18773                         }
18774 
18775                         default:            // LCOV_EXCL_LINE
18776                             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18777                     }
18778                     break;
18779                 }
18780 
18781                 default:  // decode found yet incomplete multi-byte code point
18782                 {
18783                     if (!ensure_ascii)
18784                     {
18785                         // code point will not be escaped - copy byte to buffer
18786                         string_buffer[bytes++] = s[i];
18787                     }
18788                     ++undumped_chars;
18789                     break;
18790                 }
18791             }
18792         }
18793 
18794         // we finished processing the string
18795         if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18796         {
18797             // write buffer
18798             if (bytes > 0)
18799             {
18800                 o->write_characters(string_buffer.data(), bytes);
18801             }
18802         }
18803         else
18804         {
18805             // we finish reading, but do not accept: string was incomplete
18806             switch (error_handler)
18807             {
18808                 case error_handler_t::strict:
18809                 {
18810                     JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
18811                 }
18812 
18813                 case error_handler_t::ignore:
18814                 {
18815                     // write all accepted bytes
18816                     o->write_characters(string_buffer.data(), bytes_after_last_accept);
18817                     break;
18818                 }
18819 
18820                 case error_handler_t::replace:
18821                 {
18822                     // write all accepted bytes
18823                     o->write_characters(string_buffer.data(), bytes_after_last_accept);
18824                     // add a replacement character
18825                     if (ensure_ascii)
18826                     {
18827                         o->write_characters("\\ufffd", 6);
18828                     }
18829                     else
18830                     {
18831                         o->write_characters("\xEF\xBF\xBD", 3);
18832                     }
18833                     break;
18834                 }
18835 
18836                 default:            // LCOV_EXCL_LINE
18837                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18838             }
18839         }
18840     }
18841 
18842   private:
18843     /*! 
18844     @brief count digits 
18845  
18846     Count the number of decimal (base 10) digits for an input unsigned integer. 
18847  
18848     @param[in] x  unsigned integer number to count its digits 
18849     @return    number of decimal digits 
18850     */
18851     unsigned int count_digits(number_unsigned_t x) noexcept
18852     {
18853         unsigned int n_digits = 1;
18854         for (;;)
18855         {
18856             if (x < 10)
18857             {
18858                 return n_digits;
18859             }
18860             if (x < 100)
18861             {
18862                 return n_digits + 1;
18863             }
18864             if (x < 1000)
18865             {
18866                 return n_digits + 2;
18867             }
18868             if (x < 10000)
18869             {
18870                 return n_digits + 3;
18871             }
18872             x = x / 10000u;
18873             n_digits += 4;
18874         }
18875     }
18876 
18877     /*! 
18878      * @brief convert a byte to a uppercase hex representation 
18879      * @param[in] byte byte to represent 
18880      * @return representation ("00".."FF") 
18881      */
18882     static std::string hex_bytes(std::uint8_t byte)
18883     {
18884         std::string result = "FF";
18885         constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18886         result[0] = nibble_to_hex[byte / 16];
18887         result[1] = nibble_to_hex[byte % 16];
18888         return result;
18889     }
18890 
18891     // templates to avoid warnings about useless casts
18892     template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18893     bool is_negative_number(NumberType x)
18894     {
18895         return x < 0;
18896     }
18897 
18898     template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18899     bool is_negative_number(NumberType /*unused*/)
18900     {
18901         return false;
18902     }
18903 
18904     /*! 
18905     @brief dump an integer 
18906  
18907     Dump a given integer to output stream @a o. Works internally with 
18908     @a number_buffer. 
18909  
18910     @param[in] x  integer number (signed or unsigned) to dump 
18911     @tparam NumberType either @a number_integer_t or @a number_unsigned_t 
18912     */
18913     template < typename NumberType, detail::enable_if_t <
18914                    std::is_integral<NumberType>::value ||
18915                    std::is_same<NumberType, number_unsigned_t>::value ||
18916                    std::is_same<NumberType, number_integer_t>::value ||
18917                    std::is_same<NumberType, binary_char_t>::value,
18918                    int > = 0 >
18919     void dump_integer(NumberType x)
18920     {
18921         static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18922         {
18923             {
18924                 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18925                 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18926                 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18927                 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18928                 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18929                 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18930                 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18931                 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18932                 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18933                 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18934             }
18935         };
18936 
18937         // special case for "0"
18938         if (x == 0)
18939         {
18940             o->write_character('0');
18941             return;
18942         }
18943 
18944         // use a pointer to fill the buffer
18945         auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18946 
18947         number_unsigned_t abs_value;
18948 
18949         unsigned int n_chars{};
18950 
18951         if (is_negative_number(x))
18952         {
18953             *buffer_ptr = '-';
18954             abs_value = remove_sign(static_cast<number_integer_t>(x));
18955 
18956             // account one more byte for the minus sign
18957             n_chars = 1 + count_digits(abs_value);
18958         }
18959         else
18960         {
18961             abs_value = static_cast<number_unsigned_t>(x);
18962             n_chars = count_digits(abs_value);
18963         }
18964 
18965         // spare 1 byte for '\0'
18966         JSON_ASSERT(n_chars < number_buffer.size() - 1);
18967 
18968         // jump to the end to generate the string from backward,
18969         // so we later avoid reversing the result
18970         buffer_ptr += n_chars;
18971 
18972         // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18973         // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18974         while (abs_value >= 100)
18975         {
18976             const auto digits_index = static_cast<unsigned>((abs_value % 100));
18977             abs_value /= 100;
18978             *(--buffer_ptr) = digits_to_99[digits_index][1];
18979             *(--buffer_ptr) = digits_to_99[digits_index][0];
18980         }
18981 
18982         if (abs_value >= 10)
18983         {
18984             const auto digits_index = static_cast<unsigned>(abs_value);
18985             *(--buffer_ptr) = digits_to_99[digits_index][1];
18986             *(--buffer_ptr) = digits_to_99[digits_index][0];
18987         }
18988         else
18989         {
18990             *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18991         }
18992 
18993         o->write_characters(number_buffer.data(), n_chars);
18994     }
18995 
18996     /*! 
18997     @brief dump a floating-point number 
18998  
18999     Dump a given floating-point number to output stream @a o. Works internally 
19000     with @a number_buffer. 
19001  
19002     @param[in] x  floating-point number to dump 
19003     */
19004     void dump_float(number_float_t x)
19005     {
19006         // NaN / inf
19007         if (!std::isfinite(x))
19008         {
19009             o->write_characters("null", 4);
19010             return;
19011         }
19012 
19013         // If number_float_t is an IEEE-754 single or double precision number,
19014         // use the Grisu2 algorithm to produce short numbers which are
19015         // guaranteed to round-trip, using strtof and strtod, resp.
19016         //
19017         // NB: The test below works if <long double> == <double>.
19018         static constexpr bool is_ieee_single_or_double
19019             = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
19020               (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
19021 
19022         dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19023     }
19024 
19025     void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19026     {
19027         auto* begin = number_buffer.data();
19028         auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19029 
19030         o->write_characters(begin, static_cast<size_t>(end - begin));
19031     }
19032 
19033     void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19034     {
19035         // get number of digits for a float -> text -> float round-trip
19036         static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19037 
19038         // the actual conversion
19039         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19040         std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19041 
19042         // negative value indicates an error
19043         JSON_ASSERT(len > 0);
19044         // check if buffer was large enough
19045         JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19046 
19047         // erase thousands separator
19048         if (thousands_sep != '\0')
19049         {
19050             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19051             const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19052             std::fill(end, number_buffer.end(), '\0');
19053             JSON_ASSERT((end - number_buffer.begin()) <= len);
19054             len = (end - number_buffer.begin());
19055         }
19056 
19057         // convert decimal point to '.'
19058         if (decimal_point != '\0' && decimal_point != '.')
19059         {
19060             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19061             const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19062             if (dec_pos != number_buffer.end())
19063             {
19064                 *dec_pos = '.';
19065             }
19066         }
19067 
19068         o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19069 
19070         // determine if we need to append ".0"
19071         const bool value_is_int_like =
19072             std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19073                          [](char c)
19074         {
19075             return c == '.' || c == 'e';
19076         });
19077 
19078         if (value_is_int_like)
19079         {
19080             o->write_characters(".0", 2);
19081         }
19082     }
19083 
19084     /*! 
19085     @brief check whether a string is UTF-8 encoded 
19086  
19087     The function checks each byte of a string whether it is UTF-8 encoded. The 
19088     result of the check is stored in the @a state parameter. The function must 
19089     be called initially with state 0 (accept). State 1 means the string must 
19090     be rejected, because the current byte is not allowed. If the string is 
19091     completely processed, but the state is non-zero, the string ended 
19092     prematurely; that is, the last byte indicated more bytes should have 
19093     followed. 
19094  
19095     @param[in,out] state  the state of the decoding 
19096     @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT) 
19097     @param[in] byte       next byte to decode 
19098     @return               new state 
19099  
19100     @note The function has been edited: a std::array is used. 
19101  
19102     @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> 
19103     @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 
19104     */
19105     static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19106     {
19107         static const std::array<std::uint8_t, 400> utf8d =
19108         {
19109             {
19110                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
19111                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
19112                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
19113                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
19114                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
19115                 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
19116                 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
19117                 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19118                 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19119                 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19120                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
19121                 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
19122                 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
19123                 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
19124             }
19125         };
19126 
19127         JSON_ASSERT(byte < utf8d.size());
19128         const std::uint8_t type = utf8d[byte];
19129 
19130         codep = (state != UTF8_ACCEPT)
19131                 ? (byte & 0x3fu) | (codep << 6u)
19132                 : (0xFFu >> type) & (byte);
19133 
19134         const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19135         JSON_ASSERT(index < utf8d.size());
19136         state = utf8d[index];
19137         return state;
19138     }
19139 
19140     /* 
19141      * Overload to make the compiler happy while it is instantiating 
19142      * dump_integer for number_unsigned_t. 
19143      * Must never be called. 
19144      */
19145     number_unsigned_t remove_sign(number_unsigned_t x)
19146     {
19147         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19148         return x; // LCOV_EXCL_LINE
19149     }
19150 
19151     /* 
19152      * Helper function for dump_integer 
19153      * 
19154      * This function takes a negative signed integer and returns its absolute 
19155      * value as unsigned integer. The plus/minus shuffling is necessary as we can 
19156      * not directly remove the sign of an arbitrary signed integer as the 
19157      * absolute values of INT_MIN and INT_MAX are usually not the same. See 
19158      * #1708 for details. 
19159      */
19160     number_unsigned_t remove_sign(number_integer_t x) noexcept
19161     {
19162         JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19163         return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19164     }
19165 
19166   private:
19167     /// the output of the serializer
19168     output_adapter_t<char> o = nullptr;
19169 
19170     /// a (hopefully) large enough character buffer
19171     std::array<char, 64> number_buffer{{}};
19172 
19173     /// the locale
19174     const std::lconv* loc = nullptr;
19175     /// the locale's thousand separator character
19176     const char thousands_sep = '\0';
19177     /// the locale's decimal point character
19178     const char decimal_point = '\0';
19179 
19180     /// string buffer
19181     std::array<char, 512> string_buffer{{}};
19182 
19183     /// the indentation character
19184     const char indent_char;
19185     /// the indentation string
19186     string_t indent_string;
19187 
19188     /// error_handler how to react on decoding errors
19189     const error_handler_t error_handler;
19190 };
19191 
19192 }  // namespace detail
19193 NLOHMANN_JSON_NAMESPACE_END
19194 
19195 // #include <nlohmann/detail/value_t.hpp>
19196 
19197 // #include <nlohmann/json_fwd.hpp>
19198 
19199 // #include <nlohmann/ordered_map.hpp>
19200 //     __ _____ _____ _____
19201 //  __|  |   __|     |   | |  JSON for Modern C++
19202 // |  |  |__   |  |  | | | |  version 3.11.3
19203 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
19204 //
19205 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
19206 // SPDX-License-Identifier: MIT
19207 
19208 
19209 
19210 #include <functional> // equal_to, less
19211 #include <initializer_list> // initializer_list
19212 #include <iterator> // input_iterator_tag, iterator_traits
19213 #include <memory> // allocator
19214 #include <stdexcept> // for out_of_range
19215 #include <type_traits> // enable_if, is_convertible
19216 #include <utility> // pair
19217 #include <vector> // vector
19218 
19219 // #include <nlohmann/detail/macro_scope.hpp>
19220 
19221 // #include <nlohmann/detail/meta/type_traits.hpp>
19222 
19223 
19224 NLOHMANN_JSON_NAMESPACE_BEGIN
19225 
19226 /// ordered_map: a minimal map-like container that preserves insertion order
19227 /// for use within nlohmann::basic_json<ordered_map>
19228 template <class Key, class T, class IgnoredLess = std::less<Key>,
19229           class Allocator = std::allocator<std::pair<const Key, T>>>
19230                   struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19231 {
19232     using key_type = Key;
19233     using mapped_type = T;
19234     using Container = std::vector<std::pair<const Key, T>, Allocator>;
19235     using iterator = typename Container::iterator;
19236     using const_iterator = typename Container::const_iterator;
19237     using size_type = typename Container::size_type;
19238     using value_type = typename Container::value_type;
19239 #ifdef JSON_HAS_CPP_14
19240     using key_compare = std::equal_to<>;
19241 #else
19242     using key_compare = std::equal_to<Key>;
19243 #endif
19244 
19245     // Explicit constructors instead of `using Container::Container`
19246     // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19247     ordered_map() noexcept(noexcept(Container())) : Container{} {}
19248     explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19249     template <class It>
19250     ordered_map(It first, It last, const Allocator& alloc = Allocator())
19251         : Container{first, last, alloc} {}
19252     ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19253         : Container{init, alloc} {}
19254 
19255     std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19256     {
19257         for (auto it = this->begin(); it != this->end(); ++it)
19258         {
19259             if (m_compare(it->first, key))
19260             {
19261                 return {it, false};
19262             }
19263         }
19264         Container::emplace_back(key, std::forward<T>(t));
19265         return {std::prev(this->end()), true};
19266     }
19267 
19268     template<class KeyType, detail::enable_if_t<
19269                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19270     std::pair<iterator, bool> emplace(KeyType && key, T && t)
19271     {
19272         for (auto it = this->begin(); it != this->end(); ++it)
19273         {
19274             if (m_compare(it->first, key))
19275             {
19276                 return {it, false};
19277             }
19278         }
19279         Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19280         return {std::prev(this->end()), true};
19281     }
19282 
19283     T& operator[](const key_type& key)
19284     {
19285         return emplace(key, T{}).first->second;
19286     }
19287 
19288     template<class KeyType, detail::enable_if_t<
19289                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19290     T & operator[](KeyType && key)
19291     {
19292         return emplace(std::forward<KeyType>(key), T{}).first->second;
19293     }
19294 
19295     const T& operator[](const key_type& key) const
19296     {
19297         return at(key);
19298     }
19299 
19300     template<class KeyType, detail::enable_if_t<
19301                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19302     const T & operator[](KeyType && key) const
19303     {
19304         return at(std::forward<KeyType>(key));
19305     }
19306 
19307     T& at(const key_type& key)
19308     {
19309         for (auto it = this->begin(); it != this->end(); ++it)
19310         {
19311             if (m_compare(it->first, key))
19312             {
19313                 return it->second;
19314             }
19315         }
19316 
19317         JSON_THROW(std::out_of_range("key not found"));
19318     }
19319 
19320     template<class KeyType, detail::enable_if_t<
19321                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19322     T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19323     {
19324         for (auto it = this->begin(); it != this->end(); ++it)
19325         {
19326             if (m_compare(it->first, key))
19327             {
19328                 return it->second;
19329             }
19330         }
19331 
19332         JSON_THROW(std::out_of_range("key not found"));
19333     }
19334 
19335     const T& at(const key_type& key) const
19336     {
19337         for (auto it = this->begin(); it != this->end(); ++it)
19338         {
19339             if (m_compare(it->first, key))
19340             {
19341                 return it->second;
19342             }
19343         }
19344 
19345         JSON_THROW(std::out_of_range("key not found"));
19346     }
19347 
19348     template<class KeyType, detail::enable_if_t<
19349                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19350     const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19351     {
19352         for (auto it = this->begin(); it != this->end(); ++it)
19353         {
19354             if (m_compare(it->first, key))
19355             {
19356                 return it->second;
19357             }
19358         }
19359 
19360         JSON_THROW(std::out_of_range("key not found"));
19361     }
19362 
19363     size_type erase(const key_type& key)
19364     {
19365         for (auto it = this->begin(); it != this->end(); ++it)
19366         {
19367             if (m_compare(it->first, key))
19368             {
19369                 // Since we cannot move const Keys, re-construct them in place
19370                 for (auto next = it; ++next != this->end(); ++it)
19371                 {
19372                     it->~value_type(); // Destroy but keep allocation
19373                     new (&*it) value_type{std::move(*next)};
19374                 }
19375                 Container::pop_back();
19376                 return 1;
19377             }
19378         }
19379         return 0;
19380     }
19381 
19382     template<class KeyType, detail::enable_if_t<
19383                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19384     size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19385     {
19386         for (auto it = this->begin(); it != this->end(); ++it)
19387         {
19388             if (m_compare(it->first, key))
19389             {
19390                 // Since we cannot move const Keys, re-construct them in place
19391                 for (auto next = it; ++next != this->end(); ++it)
19392                 {
19393                     it->~value_type(); // Destroy but keep allocation
19394                     new (&*it) value_type{std::move(*next)};
19395                 }
19396                 Container::pop_back();
19397                 return 1;
19398             }
19399         }
19400         return 0;
19401     }
19402 
19403     iterator erase(iterator pos)
19404     {
19405         return erase(pos, std::next(pos));
19406     }
19407 
19408     iterator erase(iterator first, iterator last)
19409     {
19410         if (first == last)
19411         {
19412             return first;
19413         }
19414 
19415         const auto elements_affected = std::distance(first, last);
19416         const auto offset = std::distance(Container::begin(), first);
19417 
19418         // This is the start situation. We need to delete elements_affected
19419         // elements (3 in this example: e, f, g), and need to return an
19420         // iterator past the last deleted element (h in this example).
19421         // Note that offset is the distance from the start of the vector
19422         // to first. We will need this later.
19423 
19424         // [ a, b, c, d, e, f, g, h, i, j ]
19425         //               ^        ^
19426         //             first    last
19427 
19428         // Since we cannot move const Keys, we re-construct them in place.
19429         // We start at first and re-construct (viz. copy) the elements from
19430         // the back of the vector. Example for first iteration:
19431 
19432         //               ,--------.
19433         //               v        |   destroy e and re-construct with h
19434         // [ a, b, c, d, e, f, g, h, i, j ]
19435         //               ^        ^
19436         //               it       it + elements_affected
19437 
19438         for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19439         {
19440             it->~value_type(); // destroy but keep allocation
19441             new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19442         }
19443 
19444         // [ a, b, c, d, h, i, j, h, i, j ]
19445         //               ^        ^
19446         //             first    last
19447 
19448         // remove the unneeded elements at the end of the vector
19449         Container::resize(this->size() - static_cast<size_type>(elements_affected));
19450 
19451         // [ a, b, c, d, h, i, j ]
19452         //               ^        ^
19453         //             first    last
19454 
19455         // first is now pointing past the last deleted element, but we cannot
19456         // use this iterator, because it may have been invalidated by the
19457         // resize call. Instead, we can return begin() + offset.
19458         return Container::begin() + offset;
19459     }
19460 
19461     size_type count(const key_type& key) const
19462     {
19463         for (auto it = this->begin(); it != this->end(); ++it)
19464         {
19465             if (m_compare(it->first, key))
19466             {
19467                 return 1;
19468             }
19469         }
19470         return 0;
19471     }
19472 
19473     template<class KeyType, detail::enable_if_t<
19474                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19475     size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19476     {
19477         for (auto it = this->begin(); it != this->end(); ++it)
19478         {
19479             if (m_compare(it->first, key))
19480             {
19481                 return 1;
19482             }
19483         }
19484         return 0;
19485     }
19486 
19487     iterator find(const key_type& key)
19488     {
19489         for (auto it = this->begin(); it != this->end(); ++it)
19490         {
19491             if (m_compare(it->first, key))
19492             {
19493                 return it;
19494             }
19495         }
19496         return Container::end();
19497     }
19498 
19499     template<class KeyType, detail::enable_if_t<
19500                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19501     iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19502     {
19503         for (auto it = this->begin(); it != this->end(); ++it)
19504         {
19505             if (m_compare(it->first, key))
19506             {
19507                 return it;
19508             }
19509         }
19510         return Container::end();
19511     }
19512 
19513     const_iterator find(const key_type& key) const
19514     {
19515         for (auto it = this->begin(); it != this->end(); ++it)
19516         {
19517             if (m_compare(it->first, key))
19518             {
19519                 return it;
19520             }
19521         }
19522         return Container::end();
19523     }
19524 
19525     std::pair<iterator, bool> insert( value_type&& value )
19526     {
19527         return emplace(value.first, std::move(value.second));
19528     }
19529 
19530     std::pair<iterator, bool> insert( const value_type& value )
19531     {
19532         for (auto it = this->begin(); it != this->end(); ++it)
19533         {
19534             if (m_compare(it->first, value.first))
19535             {
19536                 return {it, false};
19537             }
19538         }
19539         Container::push_back(value);
19540         return {--this->end(), true};
19541     }
19542 
19543     template<typename InputIt>
19544     using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19545             std::input_iterator_tag>::value>::type;
19546 
19547     template<typename InputIt, typename = require_input_iter<InputIt>>
19548     void insert(InputIt first, InputIt last)
19549     {
19550         for (auto it = first; it != last; ++it)
19551         {
19552             insert(*it);
19553         }
19554     }
19555 
19556 private:
19557     JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
19558 };
19559 
19560 NLOHMANN_JSON_NAMESPACE_END
19561 
19562 
19563 #if defined(JSON_HAS_CPP_17)
19564     #if JSON_HAS_STATIC_RTTI
19565         #include <any>
19566     #endif
19567     #include <string_view>
19568 #endif
19569 
19570 /*! 
19571 @brief namespace for Niels Lohmann 
19572 @see https://github.com/nlohmann 
19573 @since version 1.0.0 
19574 */
19575 NLOHMANN_JSON_NAMESPACE_BEGIN
19576 
19577 /*! 
19578 @brief a class to store JSON values 
19579  
19580 @internal 
19581 @invariant The member variables @a m_value and @a m_type have the following 
19582 relationship: 
19583 - If `m_type == value_t::object`, then `m_value.object != nullptr`. 
19584 - If `m_type == value_t::array`, then `m_value.array != nullptr`. 
19585 - If `m_type == value_t::string`, then `m_value.string != nullptr`. 
19586 The invariants are checked by member function assert_invariant(). 
19587  
19588 @note ObjectType trick from https://stackoverflow.com/a/9860911 
19589 @endinternal 
19590  
19591 @since version 1.0.0 
19592  
19593 @nosubgrouping 
19594 */
19595 NLOHMANN_BASIC_JSON_TPL_DECLARATION
19596 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19597     : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19598 {
19599   private:
19600     template<detail::value_t> friend struct detail::external_constructor;
19601 
19602     template<typename>
19603     friend class ::nlohmann::json_pointer;
19604     // can be restored when json_pointer backwards compatibility is removed
19605     // friend ::nlohmann::json_pointer<StringType>;
19606 
19607     template<typename BasicJsonType, typename InputType>
19608     friend class ::nlohmann::detail::parser;
19609     friend ::nlohmann::detail::serializer<basic_json>;
19610     template<typename BasicJsonType>
19611     friend class ::nlohmann::detail::iter_impl;
19612     template<typename BasicJsonType, typename CharType>
19613     friend class ::nlohmann::detail::binary_writer;
19614     template<typename BasicJsonType, typename InputType, typename SAX>
19615     friend class ::nlohmann::detail::binary_reader;
19616     template<typename BasicJsonType>
19617     friend class ::nlohmann::detail::json_sax_dom_parser;
19618     template<typename BasicJsonType>
19619     friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19620     friend class ::nlohmann::detail::exception;
19621 
19622     /// workaround type for MSVC
19623     using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19624     using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19625 
19626   JSON_PRIVATE_UNLESS_TESTED:
19627     // convenience aliases for types residing in namespace detail;
19628     using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19629 
19630     template<typename InputAdapterType>
19631     static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19632         InputAdapterType adapter,
19633         detail::parser_callback_t<basic_json>cb = nullptr,
19634         const bool allow_exceptions = true,
19635         const bool ignore_comments = false
19636                                  )
19637     {
19638         return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19639                 std::move(cb), allow_exceptions, ignore_comments);
19640     }
19641 
19642   private:
19643     using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19644     template<typename BasicJsonType>
19645     using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19646     template<typename BasicJsonType>
19647     using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19648     template<typename Iterator>
19649     using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19650     template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19651 
19652     template<typename CharType>
19653     using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19654 
19655     template<typename InputType>
19656     using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19657     template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19658 
19659   JSON_PRIVATE_UNLESS_TESTED:
19660     using serializer = ::nlohmann::detail::serializer<basic_json>;
19661 
19662   public:
19663     using value_t = detail::value_t;
19664     /// JSON Pointer, see @ref nlohmann::json_pointer
19665     using json_pointer = ::nlohmann::json_pointer<StringType>;
19666     template<typename T, typename SFINAE>
19667     using json_serializer = JSONSerializer<T, SFINAE>;
19668     /// how to treat decoding errors
19669     using error_handler_t = detail::error_handler_t;
19670     /// how to treat CBOR tags
19671     using cbor_tag_handler_t = detail::cbor_tag_handler_t;
19672     /// helper type for initializer lists of basic_json values
19673     using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19674 
19675     using input_format_t = detail::input_format_t;
19676     /// SAX interface type, see @ref nlohmann::json_sax
19677     using json_sax_t = json_sax<basic_json>;
19678 
19679     ////////////////
19680     // exceptions //
19681     ////////////////
19682 
19683     /// @name exceptions
19684     /// Classes to implement user-defined exceptions.
19685     /// @{
19686 
19687     using exception = detail::exception;
19688     using parse_error = detail::parse_error;
19689     using invalid_iterator = detail::invalid_iterator;
19690     using type_error = detail::type_error;
19691     using out_of_range = detail::out_of_range;
19692     using other_error = detail::other_error;
19693 
19694     /// @}
19695 
19696     /////////////////////
19697     // container types //
19698     /////////////////////
19699 
19700     /// @name container types
19701     /// The canonic container types to use @ref basic_json like any other STL
19702     /// container.
19703     /// @{
19704 
19705     /// the type of elements in a basic_json container
19706     using value_type = basic_json;
19707 
19708     /// the type of an element reference
19709     using reference = value_type&;
19710     /// the type of an element const reference
19711     using const_reference = const value_type&;
19712 
19713     /// a type to represent differences between iterators
19714     using difference_type = std::ptrdiff_t;
19715     /// a type to represent container sizes
19716     using size_type = std::size_t;
19717 
19718     /// the allocator type
19719     using allocator_type = AllocatorType<basic_json>;
19720 
19721     /// the type of an element pointer
19722     using pointer = typename std::allocator_traits<allocator_type>::pointer;
19723     /// the type of an element const pointer
19724     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19725 
19726     /// an iterator for a basic_json container
19727     using iterator = iter_impl<basic_json>;
19728     /// a const iterator for a basic_json container
19729     using const_iterator = iter_impl<const basic_json>;
19730     /// a reverse iterator for a basic_json container
19731     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19732     /// a const reverse iterator for a basic_json container
19733     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19734 
19735     /// @}
19736 
19737     /// @brief returns the allocator associated with the container
19738     /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
19739     static allocator_type get_allocator()
19740     {
19741         return allocator_type();
19742     }
19743 
19744     /// @brief returns version information on the library
19745     /// @sa https://json.nlohmann.me/api/basic_json/meta/
19746     JSON_HEDLEY_WARN_UNUSED_RESULT
19747     static basic_json meta()
19748     {
19749         basic_json result;
19750 
19751         result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19752         result["name"] = "JSON for Modern C++";
19753         result["url"] = "https://github.com/nlohmann/json";
19754         result["version"]["string"] =
19755             detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19756                            std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19757                            std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19758         result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19759         result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19760         result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19761 
19762 #ifdef _WIN32
19763         result["platform"] = "win32";
19764 #elif defined __linux__
19765         result["platform"] = "linux";
19766 #elif defined __APPLE__
19767         result["platform"] = "apple";
19768 #elif defined __unix__
19769         result["platform"] = "unix";
19770 #else
19771         result["platform"] = "unknown";
19772 #endif
19773 
19774 #if defined(__ICC) || defined(__INTEL_COMPILER)
19775         result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19776 #elif defined(__clang__)
19777         result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19778 #elif defined(__GNUC__) || defined(__GNUG__)
19779         result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19780                     std::to_string(__GNUC__), '.',
19781                     std::to_string(__GNUC_MINOR__), '.',
19782                     std::to_string(__GNUC_PATCHLEVEL__))
19783             }
19784         };
19785 #elif defined(__HP_cc) || defined(__HP_aCC)
19786         result["compiler"] = "hp"
19787 #elif defined(__IBMCPP__)
19788         result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19789 #elif defined(_MSC_VER)
19790         result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19791 #elif defined(__PGI)
19792         result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19793 #elif defined(__SUNPRO_CC)
19794         result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19795 #else
19796         result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19797 #endif
19798 
19799 #if defined(_MSVC_LANG)
19800         result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19801 #elif defined(__cplusplus)
19802         result["compiler"]["c++"] = std::to_string(__cplusplus);
19803 #else
19804         result["compiler"]["c++"] = "unknown";
19805 #endif
19806         return result;
19807     }
19808 
19809     ///////////////////////////
19810     // JSON value data types //
19811     ///////////////////////////
19812 
19813     /// @name JSON value data types
19814     /// The data types to store a JSON value. These types are derived from
19815     /// the template arguments passed to class @ref basic_json.
19816     /// @{
19817 
19818     /// @brief default object key comparator type
19819     /// The actual object key comparator type (@ref object_comparator_t) may be
19820     /// different.
19821     /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
19822 #if defined(JSON_HAS_CPP_14)
19823     // use of transparent comparator avoids unnecessary repeated construction of temporaries
19824     // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19825     using default_object_comparator_t = std::less<>;
19826 #else
19827     using default_object_comparator_t = std::less<StringType>;
19828 #endif
19829 
19830     /// @brief a type for an object
19831     /// @sa https://json.nlohmann.me/api/basic_json/object_t/
19832     using object_t = ObjectType<StringType,
19833           basic_json,
19834           default_object_comparator_t,
19835           AllocatorType<std::pair<const StringType,
19836           basic_json>>>;
19837 
19838     /// @brief a type for an array
19839     /// @sa https://json.nlohmann.me/api/basic_json/array_t/
19840     using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19841 
19842     /// @brief a type for a string
19843     /// @sa https://json.nlohmann.me/api/basic_json/string_t/
19844     using string_t = StringType;
19845 
19846     /// @brief a type for a boolean
19847     /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
19848     using boolean_t = BooleanType;
19849 
19850     /// @brief a type for a number (integer)
19851     /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
19852     using number_integer_t = NumberIntegerType;
19853 
19854     /// @brief a type for a number (unsigned)
19855     /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
19856     using number_unsigned_t = NumberUnsignedType;
19857 
19858     /// @brief a type for a number (floating-point)
19859     /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
19860     using number_float_t = NumberFloatType;
19861 
19862     /// @brief a type for a packed binary type
19863     /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
19864     using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19865 
19866     /// @brief object key comparator type
19867     /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
19868     using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19869 
19870     /// @}
19871 
19872   private:
19873 
19874     /// helper for exception-safe object creation
19875     template<typename T, typename... Args>
19876     JSON_HEDLEY_RETURNS_NON_NULL
19877     static T* create(Args&& ... args)
19878     {
19879         AllocatorType<T> alloc;
19880         using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19881 
19882         auto deleter = [&](T * obj)
19883         {
19884             AllocatorTraits::deallocate(alloc, obj, 1);
19885         };
19886         std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19887         AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19888         JSON_ASSERT(obj != nullptr);
19889         return obj.release();
19890     }
19891 
19892     ////////////////////////
19893     // JSON value storage //
19894     ////////////////////////
19895 
19896   JSON_PRIVATE_UNLESS_TESTED:
19897     /*! 
19898     @brief a JSON value 
19899  
19900     The actual storage for a JSON value of the @ref basic_json class. This 
19901     union combines the different storage types for the JSON value types 
19902     defined in @ref value_t. 
19903  
19904     JSON type | value_t type    | used type 
19905     --------- | --------------- | ------------------------ 
19906     object    | object          | pointer to @ref object_t 
19907     array     | array           | pointer to @ref array_t 
19908     string    | string          | pointer to @ref string_t 
19909     boolean   | boolean         | @ref boolean_t 
19910     number    | number_integer  | @ref number_integer_t 
19911     number    | number_unsigned | @ref number_unsigned_t 
19912     number    | number_float    | @ref number_float_t 
19913     binary    | binary          | pointer to @ref binary_t 
19914     null      | null            | *no value is stored* 
19915  
19916     @note Variable-length types (objects, arrays, and strings) are stored as 
19917     pointers. The size of the union should not exceed 64 bits if the default 
19918     value types are used. 
19919  
19920     @since version 1.0.0 
19921     */
19922     union json_value
19923     {
19924         /// object (stored with pointer to save storage)
19925         object_t* object;
19926         /// array (stored with pointer to save storage)
19927         array_t* array;
19928         /// string (stored with pointer to save storage)
19929         string_t* string;
19930         /// binary (stored with pointer to save storage)
19931         binary_t* binary;
19932         /// boolean
19933         boolean_t boolean;
19934         /// number (integer)
19935         number_integer_t number_integer;
19936         /// number (unsigned integer)
19937         number_unsigned_t number_unsigned;
19938         /// number (floating-point)
19939         number_float_t number_float;
19940 
19941         /// default constructor (for null values)
19942         json_value() = default;
19943         /// constructor for booleans
19944         json_value(boolean_t v) noexcept : boolean(v) {}
19945         /// constructor for numbers (integer)
19946         json_value(number_integer_t v) noexcept : number_integer(v) {}
19947         /// constructor for numbers (unsigned)
19948         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19949         /// constructor for numbers (floating-point)
19950         json_value(number_float_t v) noexcept : number_float(v) {}
19951         /// constructor for empty values of a given type
19952         json_value(value_t t)
19953         {
19954             switch (t)
19955             {
19956                 case value_t::object:
19957                 {
19958                     object = create<object_t>();
19959                     break;
19960                 }
19961 
19962                 case value_t::array:
19963                 {
19964                     array = create<array_t>();
19965                     break;
19966                 }
19967 
19968                 case value_t::string:
19969                 {
19970                     string = create<string_t>("");
19971                     break;
19972                 }
19973 
19974                 case value_t::binary:
19975                 {
19976                     binary = create<binary_t>();
19977                     break;
19978                 }
19979 
19980                 case value_t::boolean:
19981                 {
19982                     boolean = static_cast<boolean_t>(false);
19983                     break;
19984                 }
19985 
19986                 case value_t::number_integer:
19987                 {
19988                     number_integer = static_cast<number_integer_t>(0);
19989                     break;
19990                 }
19991 
19992                 case value_t::number_unsigned:
19993                 {
19994                     number_unsigned = static_cast<number_unsigned_t>(0);
19995                     break;
19996                 }
19997 
19998                 case value_t::number_float:
19999                 {
20000                     number_float = static_cast<number_float_t>(0.0);
20001                     break;
20002                 }
20003 
20004                 case value_t::null:
20005                 {
20006                     object = nullptr;  // silence warning, see #821
20007                     break;
20008                 }
20009 
20010                 case value_t::discarded:
20011                 default:
20012                 {
20013                     object = nullptr;  // silence warning, see #821
20014                     if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20015                     {
20016                         JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
20017                     }
20018                     break;
20019                 }
20020             }
20021         }
20022 
20023         /// constructor for strings
20024         json_value(const string_t& value) : string(create<string_t>(value)) {}
20025 
20026         /// constructor for rvalue strings
20027         json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20028 
20029         /// constructor for objects
20030         json_value(const object_t& value) : object(create<object_t>(value)) {}
20031 
20032         /// constructor for rvalue objects
20033         json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20034 
20035         /// constructor for arrays
20036         json_value(const array_t& value) : array(create<array_t>(value)) {}
20037 
20038         /// constructor for rvalue arrays
20039         json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20040 
20041         /// constructor for binary arrays
20042         json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20043 
20044         /// constructor for rvalue binary arrays
20045         json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20046 
20047         /// constructor for binary arrays (internal type)
20048         json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20049 
20050         /// constructor for rvalue binary arrays (internal type)
20051         json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20052 
20053         void destroy(value_t t)
20054         {
20055             if (
20056                 (t == value_t::object && object == nullptr) ||
20057                 (t == value_t::array && array == nullptr) ||
20058                 (t == value_t::string && string == nullptr) ||
20059                 (t == value_t::binary && binary == nullptr)
20060             )
20061             {
20062                 //not initialized (e.g. due to exception in the ctor)
20063                 return;
20064             }
20065             if (t == value_t::array || t == value_t::object)
20066             {
20067                 // flatten the current json_value to a heap-allocated stack
20068                 std::vector<basic_json> stack;
20069 
20070                 // move the top-level items to stack
20071                 if (t == value_t::array)
20072                 {
20073                     stack.reserve(array->size());
20074                     std::move(array->begin(), array->end(), std::back_inserter(stack));
20075                 }
20076                 else
20077                 {
20078                     stack.reserve(object->size());
20079                     for (auto&& it : *object)
20080                     {
20081                         stack.push_back(std::move(it.second));
20082                     }
20083                 }
20084 
20085                 while (!stack.empty())
20086                 {
20087                     // move the last item to local variable to be processed
20088                     basic_json current_item(std::move(stack.back()));
20089                     stack.pop_back();
20090 
20091                     // if current_item is array/object, move
20092                     // its children to the stack to be processed later
20093                     if (current_item.is_array())
20094                     {
20095                         std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20096 
20097                         current_item.m_data.m_value.array->clear();
20098                     }
20099                     else if (current_item.is_object())
20100                     {
20101                         for (auto&& it : *current_item.m_data.m_value.object)
20102                         {
20103                             stack.push_back(std::move(it.second));
20104                         }
20105 
20106                         current_item.m_data.m_value.object->clear();
20107                     }
20108 
20109                     // it's now safe that current_item get destructed
20110                     // since it doesn't have any children
20111                 }
20112             }
20113 
20114             switch (t)
20115             {
20116                 case value_t::object:
20117                 {
20118                     AllocatorType<object_t> alloc;
20119                     std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20120                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20121                     break;
20122                 }
20123 
20124                 case value_t::array:
20125                 {
20126                     AllocatorType<array_t> alloc;
20127                     std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20128                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20129                     break;
20130                 }
20131 
20132                 case value_t::string:
20133                 {
20134                     AllocatorType<string_t> alloc;
20135                     std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20136                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20137                     break;
20138                 }
20139 
20140                 case value_t::binary:
20141                 {
20142                     AllocatorType<binary_t> alloc;
20143                     std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20144                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20145                     break;
20146                 }
20147 
20148                 case value_t::null:
20149                 case value_t::boolean:
20150                 case value_t::number_integer:
20151                 case value_t::number_unsigned:
20152                 case value_t::number_float:
20153                 case value_t::discarded:
20154                 default:
20155                 {
20156                     break;
20157                 }
20158             }
20159         }
20160     };
20161 
20162   private:
20163     /*! 
20164     @brief checks the class invariants 
20165  
20166     This function asserts the class invariants. It needs to be called at the 
20167     end of every constructor to make sure that created objects respect the 
20168     invariant. Furthermore, it has to be called each time the type of a JSON 
20169     value is changed, because the invariant expresses a relationship between 
20170     @a m_type and @a m_value. 
20171  
20172     Furthermore, the parent relation is checked for arrays and objects: If 
20173     @a check_parents true and the value is an array or object, then the 
20174     container's elements must have the current value as parent. 
20175  
20176     @param[in] check_parents  whether the parent relation should be checked. 
20177                The value is true by default and should only be set to false 
20178                during destruction of objects when the invariant does not 
20179                need to hold. 
20180     */
20181     void assert_invariant(bool check_parents = true) const noexcept
20182     {
20183         JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20184         JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20185         JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20186         JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20187 
20188 #if JSON_DIAGNOSTICS
20189         JSON_TRY
20190         {
20191             // cppcheck-suppress assertWithSideEffect
20192             JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20193             {
20194                 return j.m_parent == this;
20195             }));
20196         }
20197         JSON_CATCH(...) {} // LCOV_EXCL_LINE
20198 #endif
20199         static_cast<void>(check_parents);
20200     }
20201 
20202     void set_parents()
20203     {
20204 #if JSON_DIAGNOSTICS
20205         switch (m_data.m_type)
20206         {
20207             case value_t::array:
20208             {
20209                 for (auto& element : *m_data.m_value.array)
20210                 {
20211                     element.m_parent = this;
20212                 }
20213                 break;
20214             }
20215 
20216             case value_t::object:
20217             {
20218                 for (auto& element : *m_data.m_value.object)
20219                 {
20220                     element.second.m_parent = this;
20221                 }
20222                 break;
20223             }
20224 
20225             case value_t::null:
20226             case value_t::string:
20227             case value_t::boolean:
20228             case value_t::number_integer:
20229             case value_t::number_unsigned:
20230             case value_t::number_float:
20231             case value_t::binary:
20232             case value_t::discarded:
20233             default:
20234                 break;
20235         }
20236 #endif
20237     }
20238 
20239     iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20240     {
20241 #if JSON_DIAGNOSTICS
20242         for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20243         {
20244             (it + i)->m_parent = this;
20245         }
20246 #else
20247         static_cast<void>(count_set_parents);
20248 #endif
20249         return it;
20250     }
20251 
20252     reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20253     {
20254 #if JSON_DIAGNOSTICS
20255         if (old_capacity != static_cast<std::size_t>(-1))
20256         {
20257             // see https://github.com/nlohmann/json/issues/2838
20258             JSON_ASSERT(type() == value_t::array);
20259             if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20260             {
20261                 // capacity has changed: update all parents
20262                 set_parents();
20263                 return j;
20264             }
20265         }
20266 
20267         // ordered_json uses a vector internally, so pointers could have
20268         // been invalidated; see https://github.com/nlohmann/json/issues/2962
20269 #ifdef JSON_HEDLEY_MSVC_VERSION
20270 #pragma warning(push )
20271 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20272 #endif
20273         if (detail::is_ordered_map<object_t>::value)
20274         {
20275             set_parents();
20276             return j;
20277         }
20278 #ifdef JSON_HEDLEY_MSVC_VERSION
20279 #pragma warning( pop )
20280 #endif
20281 
20282         j.m_parent = this;
20283 #else
20284         static_cast<void>(j);
20285         static_cast<void>(old_capacity);
20286 #endif
20287         return j;
20288     }
20289 
20290   public:
20291     //////////////////////////
20292     // JSON parser callback //
20293     //////////////////////////
20294 
20295     /// @brief parser event types
20296     /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
20297     using parse_event_t = detail::parse_event_t;
20298 
20299     /// @brief per-element parser callback type
20300     /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
20301     using parser_callback_t = detail::parser_callback_t<basic_json>;
20302 
20303     //////////////////
20304     // constructors //
20305     //////////////////
20306 
20307     /// @name constructors and destructors
20308     /// Constructors of class @ref basic_json, copy/move constructor, copy
20309     /// assignment, static functions creating objects, and the destructor.
20310     /// @{
20311 
20312     /// @brief create an empty value with a given type
20313     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20314     basic_json(const value_t v)
20315         : m_data(v)
20316     {
20317         assert_invariant();
20318     }
20319 
20320     /// @brief create a null object
20321     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20322     basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20323         : basic_json(value_t::null)
20324     {
20325         assert_invariant();
20326     }
20327 
20328     /// @brief create a JSON value from compatible types
20329     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20330     template < typename CompatibleType,
20331                typename U = detail::uncvref_t<CompatibleType>,
20332                detail::enable_if_t <
20333                    !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
20334     basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20335                 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20336                                            std::forward<CompatibleType>(val))))
20337     {
20338         JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20339         set_parents();
20340         assert_invariant();
20341     }
20342 
20343     /// @brief create a JSON value from an existing one
20344     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20345     template < typename BasicJsonType,
20346                detail::enable_if_t <
20347                    detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20348     basic_json(const BasicJsonType& val)
20349     {
20350         using other_boolean_t = typename BasicJsonType::boolean_t;
20351         using other_number_float_t = typename BasicJsonType::number_float_t;
20352         using other_number_integer_t = typename BasicJsonType::number_integer_t;
20353         using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20354         using other_string_t = typename BasicJsonType::string_t;
20355         using other_object_t = typename BasicJsonType::object_t;
20356         using other_array_t = typename BasicJsonType::array_t;
20357         using other_binary_t = typename BasicJsonType::binary_t;
20358 
20359         switch (val.type())
20360         {
20361             case value_t::boolean:
20362                 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20363                 break;
20364             case value_t::number_float:
20365                 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20366                 break;
20367             case value_t::number_integer:
20368                 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20369                 break;
20370             case value_t::number_unsigned:
20371                 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20372                 break;
20373             case value_t::string:
20374                 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20375                 break;
20376             case value_t::object:
20377                 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20378                 break;
20379             case value_t::array:
20380                 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20381                 break;
20382             case value_t::binary:
20383                 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20384                 break;
20385             case value_t::null:
20386                 *this = nullptr;
20387                 break;
20388             case value_t::discarded:
20389                 m_data.m_type = value_t::discarded;
20390                 break;
20391             default:            // LCOV_EXCL_LINE
20392                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20393         }
20394         JSON_ASSERT(m_data.m_type == val.type());
20395         set_parents();
20396         assert_invariant();
20397     }
20398 
20399     /// @brief create a container (array or object) from an initializer list
20400     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20401     basic_json(initializer_list_t init,
20402                bool type_deduction = true,
20403                value_t manual_type = value_t::array)
20404     {
20405         // check if each element is an array with two elements whose first
20406         // element is a string
20407         bool is_an_object = std::all_of(init.begin(), init.end(),
20408                                         [](const detail::json_ref<basic_json>& element_ref)
20409         {
20410             // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20411             // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20412             // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20413             return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20414         });
20415 
20416         // adjust type if type deduction is not wanted
20417         if (!type_deduction)
20418         {
20419             // if array is wanted, do not create an object though possible
20420             if (manual_type == value_t::array)
20421             {
20422                 is_an_object = false;
20423             }
20424 
20425             // if object is wanted but impossible, throw an exception
20426             if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20427             {
20428                 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20429             }
20430         }
20431 
20432         if (is_an_object)
20433         {
20434             // the initializer list is a list of pairs -> create object
20435             m_data.m_type = value_t::object;
20436             m_data.m_value = value_t::object;
20437 
20438             for (auto& element_ref : init)
20439             {
20440                 auto element = element_ref.moved_or_copied();
20441                 m_data.m_value.object->emplace(
20442                     std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20443                     std::move((*element.m_data.m_value.array)[1]));
20444             }
20445         }
20446         else
20447         {
20448             // the initializer list describes an array -> create array
20449             m_data.m_type = value_t::array;
20450             m_data.m_value.array = create<array_t>(init.begin(), init.end());
20451         }
20452 
20453         set_parents();
20454         assert_invariant();
20455     }
20456 
20457     /// @brief explicitly create a binary array (without subtype)
20458     /// @sa https://json.nlohmann.me/api/basic_json/binary/
20459     JSON_HEDLEY_WARN_UNUSED_RESULT
20460     static basic_json binary(const typename binary_t::container_type& init)
20461     {
20462         auto res = basic_json();
20463         res.m_data.m_type = value_t::binary;
20464         res.m_data.m_value = init;
20465         return res;
20466     }
20467 
20468     /// @brief explicitly create a binary array (with subtype)
20469     /// @sa https://json.nlohmann.me/api/basic_json/binary/
20470     JSON_HEDLEY_WARN_UNUSED_RESULT
20471     static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20472     {
20473         auto res = basic_json();
20474         res.m_data.m_type = value_t::binary;
20475         res.m_data.m_value = binary_t(init, subtype);
20476         return res;
20477     }
20478 
20479     /// @brief explicitly create a binary array
20480     /// @sa https://json.nlohmann.me/api/basic_json/binary/
20481     JSON_HEDLEY_WARN_UNUSED_RESULT
20482     static basic_json binary(typename binary_t::container_type&& init)
20483     {
20484         auto res = basic_json();
20485         res.m_data.m_type = value_t::binary;
20486         res.m_data.m_value = std::move(init);
20487         return res;
20488     }
20489 
20490     /// @brief explicitly create a binary array (with subtype)
20491     /// @sa https://json.nlohmann.me/api/basic_json/binary/
20492     JSON_HEDLEY_WARN_UNUSED_RESULT
20493     static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20494     {
20495         auto res = basic_json();
20496         res.m_data.m_type = value_t::binary;
20497         res.m_data.m_value = binary_t(std::move(init), subtype);
20498         return res;
20499     }
20500 
20501     /// @brief explicitly create an array from an initializer list
20502     /// @sa https://json.nlohmann.me/api/basic_json/array/
20503     JSON_HEDLEY_WARN_UNUSED_RESULT
20504     static basic_json array(initializer_list_t init = {})
20505     {
20506         return basic_json(init, false, value_t::array);
20507     }
20508 
20509     /// @brief explicitly create an object from an initializer list
20510     /// @sa https://json.nlohmann.me/api/basic_json/object/
20511     JSON_HEDLEY_WARN_UNUSED_RESULT
20512     static basic_json object(initializer_list_t init = {})
20513     {
20514         return basic_json(init, false, value_t::object);
20515     }
20516 
20517     /// @brief construct an array with count copies of given value
20518     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20519     basic_json(size_type cnt, const basic_json& val):
20520         m_data{cnt, val}
20521     {
20522         set_parents();
20523         assert_invariant();
20524     }
20525 
20526     /// @brief construct a JSON container given an iterator range
20527     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20528     template < class InputIT, typename std::enable_if <
20529                    std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20530                    std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20531     basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
20532     {
20533         JSON_ASSERT(first.m_object != nullptr);
20534         JSON_ASSERT(last.m_object != nullptr);
20535 
20536         // make sure iterator fits the current value
20537         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20538         {
20539             JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20540         }
20541 
20542         // copy type from first iterator
20543         m_data.m_type = first.m_object->m_data.m_type;
20544 
20545         // check if iterator range is complete for primitive values
20546         switch (m_data.m_type)
20547         {
20548             case value_t::boolean:
20549             case value_t::number_float:
20550             case value_t::number_integer:
20551             case value_t::number_unsigned:
20552             case value_t::string:
20553             {
20554                 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20555                                          || !last.m_it.primitive_iterator.is_end()))
20556                 {
20557                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20558                 }
20559                 break;
20560             }
20561 
20562             case value_t::null:
20563             case value_t::object:
20564             case value_t::array:
20565             case value_t::binary:
20566             case value_t::discarded:
20567             default:
20568                 break;
20569         }
20570 
20571         switch (m_data.m_type)
20572         {
20573             case value_t::number_integer:
20574             {
20575                 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20576                 break;
20577             }
20578 
20579             case value_t::number_unsigned:
20580             {
20581                 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20582                 break;
20583             }
20584 
20585             case value_t::number_float:
20586             {
20587                 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20588                 break;
20589             }
20590 
20591             case value_t::boolean:
20592             {
20593                 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20594                 break;
20595             }
20596 
20597             case value_t::string:
20598             {
20599                 m_data.m_value = *first.m_object->m_data.m_value.string;
20600                 break;
20601             }
20602 
20603             case value_t::object:
20604             {
20605                 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20606                                         last.m_it.object_iterator);
20607                 break;
20608             }
20609 
20610             case value_t::array:
20611             {
20612                 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20613                                                        last.m_it.array_iterator);
20614                 break;
20615             }
20616 
20617             case value_t::binary:
20618             {
20619                 m_data.m_value = *first.m_object->m_data.m_value.binary;
20620                 break;
20621             }
20622 
20623             case value_t::null:
20624             case value_t::discarded:
20625             default:
20626                 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20627         }
20628 
20629         set_parents();
20630         assert_invariant();
20631     }
20632 
20633     ///////////////////////////////////////
20634     // other constructors and destructor //
20635     ///////////////////////////////////////
20636 
20637     template<typename JsonRef,
20638              detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
20639                                  std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20640     basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20641 
20642     /// @brief copy constructor
20643     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20644     basic_json(const basic_json& other)
20645         : json_base_class_t(other)
20646     {
20647         m_data.m_type = other.m_data.m_type;
20648         // check of passed value is valid
20649         other.assert_invariant();
20650 
20651         switch (m_data.m_type)
20652         {
20653             case value_t::object:
20654             {
20655                 m_data.m_value = *other.m_data.m_value.object;
20656                 break;
20657             }
20658 
20659             case value_t::array:
20660             {
20661                 m_data.m_value = *other.m_data.m_value.array;
20662                 break;
20663             }
20664 
20665             case value_t::string:
20666             {
20667                 m_data.m_value = *other.m_data.m_value.string;
20668                 break;
20669             }
20670 
20671             case value_t::boolean:
20672             {
20673                 m_data.m_value = other.m_data.m_value.boolean;
20674                 break;
20675             }
20676 
20677             case value_t::number_integer:
20678             {
20679                 m_data.m_value = other.m_data.m_value.number_integer;
20680                 break;
20681             }
20682 
20683             case value_t::number_unsigned:
20684             {
20685                 m_data.m_value = other.m_data.m_value.number_unsigned;
20686                 break;
20687             }
20688 
20689             case value_t::number_float:
20690             {
20691                 m_data.m_value = other.m_data.m_value.number_float;
20692                 break;
20693             }
20694 
20695             case value_t::binary:
20696             {
20697                 m_data.m_value = *other.m_data.m_value.binary;
20698                 break;
20699             }
20700 
20701             case value_t::null:
20702             case value_t::discarded:
20703             default:
20704                 break;
20705         }
20706 
20707         set_parents();
20708         assert_invariant();
20709     }
20710 
20711     /// @brief move constructor
20712     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20713     basic_json(basic_json&& other) noexcept
20714         : json_base_class_t(std::forward<json_base_class_t>(other)),
20715           m_data(std::move(other.m_data))
20716     {
20717         // check that passed value is valid
20718         other.assert_invariant(false);
20719 
20720         // invalidate payload
20721         other.m_data.m_type = value_t::null;
20722         other.m_data.m_value = {};
20723 
20724         set_parents();
20725         assert_invariant();
20726     }
20727 
20728     /// @brief copy assignment
20729     /// @sa https://json.nlohmann.me/api/basic_json/operator=/
20730     basic_json& operator=(basic_json other) noexcept (
20731         std::is_nothrow_move_constructible<value_t>::value&&
20732         std::is_nothrow_move_assignable<value_t>::value&&
20733         std::is_nothrow_move_constructible<json_value>::value&&
20734         std::is_nothrow_move_assignable<json_value>::value&&
20735         std::is_nothrow_move_assignable<json_base_class_t>::value
20736     )
20737     {
20738         // check that passed value is valid
20739         other.assert_invariant();
20740 
20741         using std::swap;
20742         swap(m_data.m_type, other.m_data.m_type);
20743         swap(m_data.m_value, other.m_data.m_value);
20744         json_base_class_t::operator=(std::move(other));
20745 
20746         set_parents();
20747         assert_invariant();
20748         return *this;
20749     }
20750 
20751     /// @brief destructor
20752     /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
20753     ~basic_json() noexcept
20754     {
20755         assert_invariant(false);
20756     }
20757 
20758     /// @}
20759 
20760   public:
20761     ///////////////////////
20762     // object inspection //
20763     ///////////////////////
20764 
20765     /// @name object inspection
20766     /// Functions to inspect the type of a JSON value.
20767     /// @{
20768 
20769     /// @brief serialization
20770     /// @sa https://json.nlohmann.me/api/basic_json/dump/
20771     string_t dump(const int indent = -1,
20772                   const char indent_char = ' ',
20773                   const bool ensure_ascii = false,
20774                   const error_handler_t error_handler = error_handler_t::strict) const
20775     {
20776         string_t result;
20777         serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20778 
20779         if (indent >= 0)
20780         {
20781             s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20782         }
20783         else
20784         {
20785             s.dump(*this, false, ensure_ascii, 0);
20786         }
20787 
20788         return result;
20789     }
20790 
20791     /// @brief return the type of the JSON value (explicit)
20792     /// @sa https://json.nlohmann.me/api/basic_json/type/
20793     constexpr value_t type() const noexcept
20794     {
20795         return m_data.m_type;
20796     }
20797 
20798     /// @brief return whether type is primitive
20799     /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
20800     constexpr bool is_primitive() const noexcept
20801     {
20802         return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20803     }
20804 
20805     /// @brief return whether type is structured
20806     /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
20807     constexpr bool is_structured() const noexcept
20808     {
20809         return is_array() || is_object();
20810     }
20811 
20812     /// @brief return whether value is null
20813     /// @sa https://json.nlohmann.me/api/basic_json/is_null/
20814     constexpr bool is_null() const noexcept
20815     {
20816         return m_data.m_type == value_t::null;
20817     }
20818 
20819     /// @brief return whether value is a boolean
20820     /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
20821     constexpr bool is_boolean() const noexcept
20822     {
20823         return m_data.m_type == value_t::boolean;
20824     }
20825 
20826     /// @brief return whether value is a number
20827     /// @sa https://json.nlohmann.me/api/basic_json/is_number/
20828     constexpr bool is_number() const noexcept
20829     {
20830         return is_number_integer() || is_number_float();
20831     }
20832 
20833     /// @brief return whether value is an integer number
20834     /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
20835     constexpr bool is_number_integer() const noexcept
20836     {
20837         return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20838     }
20839 
20840     /// @brief return whether value is an unsigned integer number
20841     /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
20842     constexpr bool is_number_unsigned() const noexcept
20843     {
20844         return m_data.m_type == value_t::number_unsigned;
20845     }
20846 
20847     /// @brief return whether value is a floating-point number
20848     /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
20849     constexpr bool is_number_float() const noexcept
20850     {
20851         return m_data.m_type == value_t::number_float;
20852     }
20853 
20854     /// @brief return whether value is an object
20855     /// @sa https://json.nlohmann.me/api/basic_json/is_object/
20856     constexpr bool is_object() const noexcept
20857     {
20858         return m_data.m_type == value_t::object;
20859     }
20860 
20861     /// @brief return whether value is an array
20862     /// @sa https://json.nlohmann.me/api/basic_json/is_array/
20863     constexpr bool is_array() const noexcept
20864     {
20865         return m_data.m_type == value_t::array;
20866     }
20867 
20868     /// @brief return whether value is a string
20869     /// @sa https://json.nlohmann.me/api/basic_json/is_string/
20870     constexpr bool is_string() const noexcept
20871     {
20872         return m_data.m_type == value_t::string;
20873     }
20874 
20875     /// @brief return whether value is a binary array
20876     /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
20877     constexpr bool is_binary() const noexcept
20878     {
20879         return m_data.m_type == value_t::binary;
20880     }
20881 
20882     /// @brief return whether value is discarded
20883     /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
20884     constexpr bool is_discarded() const noexcept
20885     {
20886         return m_data.m_type == value_t::discarded;
20887     }
20888 
20889     /// @brief return the type of the JSON value (implicit)
20890     /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
20891     constexpr operator value_t() const noexcept
20892     {
20893         return m_data.m_type;
20894     }
20895 
20896     /// @}
20897 
20898   private:
20899     //////////////////
20900     // value access //
20901     //////////////////
20902 
20903     /// get a boolean (explicit)
20904     boolean_t get_impl(boolean_t* /*unused*/) const
20905     {
20906         if (JSON_HEDLEY_LIKELY(is_boolean()))
20907         {
20908             return m_data.m_value.boolean;
20909         }
20910 
20911         JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20912     }
20913 
20914     /// get a pointer to the value (object)
20915     object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20916     {
20917         return is_object() ? m_data.m_value.object : nullptr;
20918     }
20919 
20920     /// get a pointer to the value (object)
20921     constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20922     {
20923         return is_object() ? m_data.m_value.object : nullptr;
20924     }
20925 
20926     /// get a pointer to the value (array)
20927     array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20928     {
20929         return is_array() ? m_data.m_value.array : nullptr;
20930     }
20931 
20932     /// get a pointer to the value (array)
20933     constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20934     {
20935         return is_array() ? m_data.m_value.array : nullptr;
20936     }
20937 
20938     /// get a pointer to the value (string)
20939     string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20940     {
20941         return is_string() ? m_data.m_value.string : nullptr;
20942     }
20943 
20944     /// get a pointer to the value (string)
20945     constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20946     {
20947         return is_string() ? m_data.m_value.string : nullptr;
20948     }
20949 
20950     /// get a pointer to the value (boolean)
20951     boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20952     {
20953         return is_boolean() ? &m_data.m_value.boolean : nullptr;
20954     }
20955 
20956     /// get a pointer to the value (boolean)
20957     constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20958     {
20959         return is_boolean() ? &m_data.m_value.boolean : nullptr;
20960     }
20961 
20962     /// get a pointer to the value (integer number)
20963     number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20964     {
20965         return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20966     }
20967 
20968     /// get a pointer to the value (integer number)
20969     constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20970     {
20971         return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20972     }
20973 
20974     /// get a pointer to the value (unsigned number)
20975     number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20976     {
20977         return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20978     }
20979 
20980     /// get a pointer to the value (unsigned number)
20981     constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20982     {
20983         return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20984     }
20985 
20986     /// get a pointer to the value (floating-point number)
20987     number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20988     {
20989         return is_number_float() ? &m_data.m_value.number_float : nullptr;
20990     }
20991 
20992     /// get a pointer to the value (floating-point number)
20993     constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20994     {
20995         return is_number_float() ? &m_data.m_value.number_float : nullptr;
20996     }
20997 
20998     /// get a pointer to the value (binary)
20999     binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21000     {
21001         return is_binary() ? m_data.m_value.binary : nullptr;
21002     }
21003 
21004     /// get a pointer to the value (binary)
21005     constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21006     {
21007         return is_binary() ? m_data.m_value.binary : nullptr;
21008     }
21009 
21010     /*! 
21011     @brief helper function to implement get_ref() 
21012  
21013     This function helps to implement get_ref() without code duplication for 
21014     const and non-const overloads 
21015  
21016     @tparam ThisType will be deduced as `basic_json` or `const basic_json` 
21017  
21018     @throw type_error.303 if ReferenceType does not match underlying value 
21019     type of the current JSON 
21020     */
21021     template<typename ReferenceType, typename ThisType>
21022     static ReferenceType get_ref_impl(ThisType& obj)
21023     {
21024         // delegate the call to get_ptr<>()
21025         auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21026 
21027         if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21028         {
21029             return *ptr;
21030         }
21031 
21032         JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21033     }
21034 
21035   public:
21036     /// @name value access
21037     /// Direct access to the stored value of a JSON value.
21038     /// @{
21039 
21040     /// @brief get a pointer value (implicit)
21041     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21042     template<typename PointerType, typename std::enable_if<
21043                  std::is_pointer<PointerType>::value, int>::type = 0>
21044     auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21045     {
21046         // delegate the call to get_impl_ptr<>()
21047         return get_impl_ptr(static_cast<PointerType>(nullptr));
21048     }
21049 
21050     /// @brief get a pointer value (implicit)
21051     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21052     template < typename PointerType, typename std::enable_if <
21053                    std::is_pointer<PointerType>::value&&
21054                    std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21055     constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21056     {
21057         // delegate the call to get_impl_ptr<>() const
21058         return get_impl_ptr(static_cast<PointerType>(nullptr));
21059     }
21060 
21061   private:
21062     /*! 
21063     @brief get a value (explicit) 
21064  
21065     Explicit type conversion between the JSON value and a compatible value 
21066     which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 
21067     and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 
21068     The value is converted by calling the @ref json_serializer<ValueType> 
21069     `from_json()` method. 
21070  
21071     The function is equivalent to executing 
21072     @code {.cpp} 
21073     ValueType ret; 
21074     JSONSerializer<ValueType>::from_json(*this, ret); 
21075     return ret; 
21076     @endcode 
21077  
21078     This overloads is chosen if: 
21079     - @a ValueType is not @ref basic_json, 
21080     - @ref json_serializer<ValueType> has a `from_json()` method of the form 
21081       `void from_json(const basic_json&, ValueType&)`, and 
21082     - @ref json_serializer<ValueType> does not have a `from_json()` method of 
21083       the form `ValueType from_json(const basic_json&)` 
21084  
21085     @tparam ValueType the returned value type 
21086  
21087     @return copy of the JSON value, converted to @a ValueType 
21088  
21089     @throw what @ref json_serializer<ValueType> `from_json()` method throws 
21090  
21091     @liveexample{The example below shows several conversions from JSON values 
21092     to other types. There a few things to note: (1) Floating-point numbers can 
21093     be converted to integers\, (2) A JSON array can be converted to a standard 
21094     `std::vector<short>`\, (3) A JSON object can be converted to C++ 
21095     associative containers such as `std::unordered_map<std::string\, 
21096     json>`.,get__ValueType_const} 
21097  
21098     @since version 2.1.0 
21099     */
21100     template < typename ValueType,
21101                detail::enable_if_t <
21102                    detail::is_default_constructible<ValueType>::value&&
21103                    detail::has_from_json<basic_json_t, ValueType>::value,
21104                    int > = 0 >
21105     ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21106                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21107     {
21108         auto ret = ValueType();
21109         JSONSerializer<ValueType>::from_json(*this, ret);
21110         return ret;
21111     }
21112 
21113     /*! 
21114     @brief get a value (explicit); special case 
21115  
21116     Explicit type conversion between the JSON value and a compatible value 
21117     which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 
21118     and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 
21119     The value is converted by calling the @ref json_serializer<ValueType> 
21120     `from_json()` method. 
21121  
21122     The function is equivalent to executing 
21123     @code {.cpp} 
21124     return JSONSerializer<ValueType>::from_json(*this); 
21125     @endcode 
21126  
21127     This overloads is chosen if: 
21128     - @a ValueType is not @ref basic_json and 
21129     - @ref json_serializer<ValueType> has a `from_json()` method of the form 
21130       `ValueType from_json(const basic_json&)` 
21131  
21132     @note If @ref json_serializer<ValueType> has both overloads of 
21133     `from_json()`, this one is chosen. 
21134  
21135     @tparam ValueType the returned value type 
21136  
21137     @return copy of the JSON value, converted to @a ValueType 
21138  
21139     @throw what @ref json_serializer<ValueType> `from_json()` method throws 
21140  
21141     @since version 2.1.0 
21142     */
21143     template < typename ValueType,
21144                detail::enable_if_t <
21145                    detail::has_non_default_from_json<basic_json_t, ValueType>::value,
21146                    int > = 0 >
21147     ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21148                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21149     {
21150         return JSONSerializer<ValueType>::from_json(*this);
21151     }
21152 
21153     /*! 
21154     @brief get special-case overload 
21155  
21156     This overloads converts the current @ref basic_json in a different 
21157     @ref basic_json type 
21158  
21159     @tparam BasicJsonType == @ref basic_json 
21160  
21161     @return a copy of *this, converted into @a BasicJsonType 
21162  
21163     @complexity Depending on the implementation of the called `from_json()` 
21164                 method. 
21165  
21166     @since version 3.2.0 
21167     */
21168     template < typename BasicJsonType,
21169                detail::enable_if_t <
21170                    detail::is_basic_json<BasicJsonType>::value,
21171                    int > = 0 >
21172     BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21173     {
21174         return *this;
21175     }
21176 
21177     /*! 
21178     @brief get special-case overload 
21179  
21180     This overloads avoids a lot of template boilerplate, it can be seen as the 
21181     identity method 
21182  
21183     @tparam BasicJsonType == @ref basic_json 
21184  
21185     @return a copy of *this 
21186  
21187     @complexity Constant. 
21188  
21189     @since version 2.1.0 
21190     */
21191     template<typename BasicJsonType,
21192              detail::enable_if_t<
21193                  std::is_same<BasicJsonType, basic_json_t>::value,
21194                  int> = 0>
21195     basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21196     {
21197         return *this;
21198     }
21199 
21200     /*! 
21201     @brief get a pointer value (explicit) 
21202     @copydoc get() 
21203     */
21204     template<typename PointerType,
21205              detail::enable_if_t<
21206                  std::is_pointer<PointerType>::value,
21207                  int> = 0>
21208     constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21209     -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21210     {
21211         // delegate the call to get_ptr
21212         return get_ptr<PointerType>();
21213     }
21214 
21215   public:
21216     /*! 
21217     @brief get a (pointer) value (explicit) 
21218  
21219     Performs explicit type conversion between the JSON value and a compatible value if required. 
21220  
21221     - If the requested type is a pointer to the internally stored JSON value that pointer is returned. 
21222     No copies are made. 
21223  
21224     - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible 
21225     from the current @ref basic_json. 
21226  
21227     - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()` 
21228     method. 
21229  
21230     @tparam ValueTypeCV the provided value type 
21231     @tparam ValueType the returned value type 
21232  
21233     @return copy of the JSON value, converted to @tparam ValueType if necessary 
21234  
21235     @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required 
21236  
21237     @since version 2.1.0 
21238     */
21239     template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21240 #if defined(JSON_HAS_CPP_14)
21241     constexpr
21242 #endif
21243     auto get() const noexcept(
21244     noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21245     -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21246     {
21247         // we cannot static_assert on ValueTypeCV being non-const, because
21248         // there is support for get<const basic_json_t>(), which is why we
21249         // still need the uncvref
21250         static_assert(!std::is_reference<ValueTypeCV>::value,
21251                       "get() cannot be used with reference types, you might want to use get_ref()");
21252         return get_impl<ValueType>(detail::priority_tag<4> {});
21253     }
21254 
21255     /*! 
21256     @brief get a pointer value (explicit) 
21257  
21258     Explicit pointer access to the internally stored JSON value. No copies are 
21259     made. 
21260  
21261     @warning The pointer becomes invalid if the underlying JSON object 
21262     changes. 
21263  
21264     @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref 
21265     object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 
21266     @ref number_unsigned_t, or @ref number_float_t. 
21267  
21268     @return pointer to the internally stored JSON value if the requested 
21269     pointer type @a PointerType fits to the JSON value; `nullptr` otherwise 
21270  
21271     @complexity Constant. 
21272  
21273     @liveexample{The example below shows how pointers to internal values of a 
21274     JSON value can be requested. Note that no type conversions are made and a 
21275     `nullptr` is returned if the value and the requested pointer type does not 
21276     match.,get__PointerType} 
21277  
21278     @sa see @ref get_ptr() for explicit pointer-member access 
21279  
21280     @since version 1.0.0 
21281     */
21282     template<typename PointerType, typename std::enable_if<
21283                  std::is_pointer<PointerType>::value, int>::type = 0>
21284     auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21285     {
21286         // delegate the call to get_ptr
21287         return get_ptr<PointerType>();
21288     }
21289 
21290     /// @brief get a value (explicit)
21291     /// @sa https://json.nlohmann.me/api/basic_json/get_to/
21292     template < typename ValueType,
21293                detail::enable_if_t <
21294                    !detail::is_basic_json<ValueType>::value&&
21295                    detail::has_from_json<basic_json_t, ValueType>::value,
21296                    int > = 0 >
21297     ValueType & get_to(ValueType& v) const noexcept(noexcept(
21298                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21299     {
21300         JSONSerializer<ValueType>::from_json(*this, v);
21301         return v;
21302     }
21303 
21304     // specialization to allow calling get_to with a basic_json value
21305     // see https://github.com/nlohmann/json/issues/2175
21306     template<typename ValueType,
21307              detail::enable_if_t <
21308                  detail::is_basic_json<ValueType>::value,
21309                  int> = 0>
21310     ValueType & get_to(ValueType& v) const
21311     {
21312         v = *this;
21313         return v;
21314     }
21315 
21316     template <
21317         typename T, std::size_t N,
21318         typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21319         detail::enable_if_t <
21320             detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
21321     Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21322     noexcept(noexcept(JSONSerializer<Array>::from_json(
21323                           std::declval<const basic_json_t&>(), v)))
21324     {
21325         JSONSerializer<Array>::from_json(*this, v);
21326         return v;
21327     }
21328 
21329     /// @brief get a reference value (implicit)
21330     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21331     template<typename ReferenceType, typename std::enable_if<
21332                  std::is_reference<ReferenceType>::value, int>::type = 0>
21333     ReferenceType get_ref()
21334     {
21335         // delegate call to get_ref_impl
21336         return get_ref_impl<ReferenceType>(*this);
21337     }
21338 
21339     /// @brief get a reference value (implicit)
21340     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21341     template < typename ReferenceType, typename std::enable_if <
21342                    std::is_reference<ReferenceType>::value&&
21343                    std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21344     ReferenceType get_ref() const
21345     {
21346         // delegate call to get_ref_impl
21347         return get_ref_impl<ReferenceType>(*this);
21348     }
21349 
21350     /*! 
21351     @brief get a value (implicit) 
21352  
21353     Implicit type conversion between the JSON value and a compatible value. 
21354     The call is realized by calling @ref get() const. 
21355  
21356     @tparam ValueType non-pointer type compatible to the JSON value, for 
21357     instance `int` for JSON integer numbers, `bool` for JSON booleans, or 
21358     `std::vector` types for JSON arrays. The character type of @ref string_t 
21359     as well as an initializer list of this type is excluded to avoid 
21360     ambiguities as these types implicitly convert to `std::string`. 
21361  
21362     @return copy of the JSON value, converted to type @a ValueType 
21363  
21364     @throw type_error.302 in case passed type @a ValueType is incompatible 
21365     to the JSON value type (e.g., the JSON value is of type boolean, but a 
21366     string is requested); see example below 
21367  
21368     @complexity Linear in the size of the JSON value. 
21369  
21370     @liveexample{The example below shows several conversions from JSON values 
21371     to other types. There a few things to note: (1) Floating-point numbers can 
21372     be converted to integers\, (2) A JSON array can be converted to a standard 
21373     `std::vector<short>`\, (3) A JSON object can be converted to C++ 
21374     associative containers such as `std::unordered_map<std::string\, 
21375     json>`.,operator__ValueType} 
21376  
21377     @since version 1.0.0 
21378     */
21379     template < typename ValueType, typename std::enable_if <
21380                    detail::conjunction <
21381                        detail::negation<std::is_pointer<ValueType>>,
21382                        detail::negation<std::is_same<ValueType, std::nullptr_t>>,
21383                        detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
21384                                         detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
21385                                         detail::negation<detail::is_basic_json<ValueType>>,
21386                                         detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
21387 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21388                                                 detail::negation<std::is_same<ValueType, std::string_view>>,
21389 #endif
21390 #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21391                                                 detail::negation<std::is_same<ValueType, std::any>>,
21392 #endif
21393                                                 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
21394                                                 >::value, int >::type = 0 >
21395                                         JSON_EXPLICIT operator ValueType() const
21396     {
21397         // delegate the call to get<>() const
21398         return get<ValueType>();
21399     }
21400 
21401     /// @brief get a binary value
21402     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21403     binary_t& get_binary()
21404     {
21405         if (!is_binary())
21406         {
21407             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21408         }
21409 
21410         return *get_ptr<binary_t*>();
21411     }
21412 
21413     /// @brief get a binary value
21414     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21415     const binary_t& get_binary() const
21416     {
21417         if (!is_binary())
21418         {
21419             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21420         }
21421 
21422         return *get_ptr<const binary_t*>();
21423     }
21424 
21425     /// @}
21426 
21427     ////////////////////
21428     // element access //
21429     ////////////////////
21430 
21431     /// @name element access
21432     /// Access to the JSON value.
21433     /// @{
21434 
21435     /// @brief access specified array element with bounds checking
21436     /// @sa https://json.nlohmann.me/api/basic_json/at/
21437     reference at(size_type idx)
21438     {
21439         // at only works for arrays
21440         if (JSON_HEDLEY_LIKELY(is_array()))
21441         {
21442             JSON_TRY
21443             {
21444                 return set_parent(m_data.m_value.array->at(idx));
21445             }
21446             JSON_CATCH (std::out_of_range&)
21447             {
21448                 // create better exception explanation
21449                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21450             }
21451         }
21452         else
21453         {
21454             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21455         }
21456     }
21457 
21458     /// @brief access specified array element with bounds checking
21459     /// @sa https://json.nlohmann.me/api/basic_json/at/
21460     const_reference at(size_type idx) const
21461     {
21462         // at only works for arrays
21463         if (JSON_HEDLEY_LIKELY(is_array()))
21464         {
21465             JSON_TRY
21466             {
21467                 return m_data.m_value.array->at(idx);
21468             }
21469             JSON_CATCH (std::out_of_range&)
21470             {
21471                 // create better exception explanation
21472                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21473             }
21474         }
21475         else
21476         {
21477             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21478         }
21479     }
21480 
21481     /// @brief access specified object element with bounds checking
21482     /// @sa https://json.nlohmann.me/api/basic_json/at/
21483     reference at(const typename object_t::key_type& key)
21484     {
21485         // at only works for objects
21486         if (JSON_HEDLEY_UNLIKELY(!is_object()))
21487         {
21488             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21489         }
21490 
21491         auto it = m_data.m_value.object->find(key);
21492         if (it == m_data.m_value.object->end())
21493         {
21494             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21495         }
21496         return set_parent(it->second);
21497     }
21498 
21499     /// @brief access specified object element with bounds checking
21500     /// @sa https://json.nlohmann.me/api/basic_json/at/
21501     template<class KeyType, detail::enable_if_t<
21502                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21503     reference at(KeyType && key)
21504     {
21505         // at only works for objects
21506         if (JSON_HEDLEY_UNLIKELY(!is_object()))
21507         {
21508             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21509         }
21510 
21511         auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21512         if (it == m_data.m_value.object->end())
21513         {
21514             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21515         }
21516         return set_parent(it->second);
21517     }
21518 
21519     /// @brief access specified object element with bounds checking
21520     /// @sa https://json.nlohmann.me/api/basic_json/at/
21521     const_reference at(const typename object_t::key_type& key) const
21522     {
21523         // at only works for objects
21524         if (JSON_HEDLEY_UNLIKELY(!is_object()))
21525         {
21526             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21527         }
21528 
21529         auto it = m_data.m_value.object->find(key);
21530         if (it == m_data.m_value.object->end())
21531         {
21532             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21533         }
21534         return it->second;
21535     }
21536 
21537     /// @brief access specified object element with bounds checking
21538     /// @sa https://json.nlohmann.me/api/basic_json/at/
21539     template<class KeyType, detail::enable_if_t<
21540                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21541     const_reference at(KeyType && key) const
21542     {
21543         // at only works for objects
21544         if (JSON_HEDLEY_UNLIKELY(!is_object()))
21545         {
21546             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21547         }
21548 
21549         auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21550         if (it == m_data.m_value.object->end())
21551         {
21552             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21553         }
21554         return it->second;
21555     }
21556 
21557     /// @brief access specified array element
21558     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21559     reference operator[](size_type idx)
21560     {
21561         // implicitly convert null value to an empty array
21562         if (is_null())
21563         {
21564             m_data.m_type = value_t::array;
21565             m_data.m_value.array = create<array_t>();
21566             assert_invariant();
21567         }
21568 
21569         // operator[] only works for arrays
21570         if (JSON_HEDLEY_LIKELY(is_array()))
21571         {
21572             // fill up array with null values if given idx is outside range
21573             if (idx >= m_data.m_value.array->size())
21574             {
21575 #if JSON_DIAGNOSTICS
21576                 // remember array size & capacity before resizing
21577                 const auto old_size = m_data.m_value.array->size();
21578                 const auto old_capacity = m_data.m_value.array->capacity();
21579 #endif
21580                 m_data.m_value.array->resize(idx + 1);
21581 
21582 #if JSON_DIAGNOSTICS
21583                 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21584                 {
21585                     // capacity has changed: update all parents
21586                     set_parents();
21587                 }
21588                 else
21589                 {
21590                     // set parent for values added above
21591                     set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21592                 }
21593 #endif
21594                 assert_invariant();
21595             }
21596 
21597             return m_data.m_value.array->operator[](idx);
21598         }
21599 
21600         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21601     }
21602 
21603     /// @brief access specified array element
21604     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21605     const_reference operator[](size_type idx) const
21606     {
21607         // const operator[] only works for arrays
21608         if (JSON_HEDLEY_LIKELY(is_array()))
21609         {
21610             return m_data.m_value.array->operator[](idx);
21611         }
21612 
21613         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21614     }
21615 
21616     /// @brief access specified object element
21617     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21618     reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
21619     {
21620         // implicitly convert null value to an empty object
21621         if (is_null())
21622         {
21623             m_data.m_type = value_t::object;
21624             m_data.m_value.object = create<object_t>();
21625             assert_invariant();
21626         }
21627 
21628         // operator[] only works for objects
21629         if (JSON_HEDLEY_LIKELY(is_object()))
21630         {
21631             auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21632             return set_parent(result.first->second);
21633         }
21634 
21635         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21636     }
21637 
21638     /// @brief access specified object element
21639     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21640     const_reference operator[](const typename object_t::key_type& key) const
21641     {
21642         // const operator[] only works for objects
21643         if (JSON_HEDLEY_LIKELY(is_object()))
21644         {
21645             auto it = m_data.m_value.object->find(key);
21646             JSON_ASSERT(it != m_data.m_value.object->end());
21647             return it->second;
21648         }
21649 
21650         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21651     }
21652 
21653     // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21654     // (they seemingly cannot be constrained to resolve the ambiguity)
21655     template<typename T>
21656     reference operator[](T* key)
21657     {
21658         return operator[](typename object_t::key_type(key));
21659     }
21660 
21661     template<typename T>
21662     const_reference operator[](T* key) const
21663     {
21664         return operator[](typename object_t::key_type(key));
21665     }
21666 
21667     /// @brief access specified object element
21668     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21669     template<class KeyType, detail::enable_if_t<
21670                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21671     reference operator[](KeyType && key)
21672     {
21673         // implicitly convert null value to an empty object
21674         if (is_null())
21675         {
21676             m_data.m_type = value_t::object;
21677             m_data.m_value.object = create<object_t>();
21678             assert_invariant();
21679         }
21680 
21681         // operator[] only works for objects
21682         if (JSON_HEDLEY_LIKELY(is_object()))
21683         {
21684             auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21685             return set_parent(result.first->second);
21686         }
21687 
21688         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21689     }
21690 
21691     /// @brief access specified object element
21692     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
21693     template<class KeyType, detail::enable_if_t<
21694                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21695     const_reference operator[](KeyType && key) const
21696     {
21697         // const operator[] only works for objects
21698         if (JSON_HEDLEY_LIKELY(is_object()))
21699         {
21700             auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21701             JSON_ASSERT(it != m_data.m_value.object->end());
21702             return it->second;
21703         }
21704 
21705         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21706     }
21707 
21708   private:
21709     template<typename KeyType>
21710     using is_comparable_with_object_key = detail::is_comparable <
21711         object_comparator_t, const typename object_t::key_type&, KeyType >;
21712 
21713     template<typename ValueType>
21714     using value_return_type = std::conditional <
21715         detail::is_c_string_uncvref<ValueType>::value,
21716         string_t, typename std::decay<ValueType>::type >;
21717 
21718   public:
21719     /// @brief access specified object element with default value
21720     /// @sa https://json.nlohmann.me/api/basic_json/value/
21721     template < class ValueType, detail::enable_if_t <
21722                    !detail::is_transparent<object_comparator_t>::value
21723                    && detail::is_getable<basic_json_t, ValueType>::value
21724                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21725     ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21726     {
21727         // value only works for objects
21728         if (JSON_HEDLEY_LIKELY(is_object()))
21729         {
21730             // if key is found, return value and given default value otherwise
21731             const auto it = find(key);
21732             if (it != end())
21733             {
21734                 return it->template get<ValueType>();
21735             }
21736 
21737             return default_value;
21738         }
21739 
21740         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21741     }
21742 
21743     /// @brief access specified object element with default value
21744     /// @sa https://json.nlohmann.me/api/basic_json/value/
21745     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21746                detail::enable_if_t <
21747                    !detail::is_transparent<object_comparator_t>::value
21748                    && detail::is_getable<basic_json_t, ReturnType>::value
21749                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21750     ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21751     {
21752         // value only works for objects
21753         if (JSON_HEDLEY_LIKELY(is_object()))
21754         {
21755             // if key is found, return value and given default value otherwise
21756             const auto it = find(key);
21757             if (it != end())
21758             {
21759                 return it->template get<ReturnType>();
21760             }
21761 
21762             return std::forward<ValueType>(default_value);
21763         }
21764 
21765         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21766     }
21767 
21768     /// @brief access specified object element with default value
21769     /// @sa https://json.nlohmann.me/api/basic_json/value/
21770     template < class ValueType, class KeyType, detail::enable_if_t <
21771                    detail::is_transparent<object_comparator_t>::value
21772                    && !detail::is_json_pointer<KeyType>::value
21773                    && is_comparable_with_object_key<KeyType>::value
21774                    && detail::is_getable<basic_json_t, ValueType>::value
21775                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21776     ValueType value(KeyType && key, const ValueType& default_value) const
21777     {
21778         // value only works for objects
21779         if (JSON_HEDLEY_LIKELY(is_object()))
21780         {
21781             // if key is found, return value and given default value otherwise
21782             const auto it = find(std::forward<KeyType>(key));
21783             if (it != end())
21784             {
21785                 return it->template get<ValueType>();
21786             }
21787 
21788             return default_value;
21789         }
21790 
21791         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21792     }
21793 
21794     /// @brief access specified object element via JSON Pointer with default value
21795     /// @sa https://json.nlohmann.me/api/basic_json/value/
21796     template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21797                detail::enable_if_t <
21798                    detail::is_transparent<object_comparator_t>::value
21799                    && !detail::is_json_pointer<KeyType>::value
21800                    && is_comparable_with_object_key<KeyType>::value
21801                    && detail::is_getable<basic_json_t, ReturnType>::value
21802                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21803     ReturnType value(KeyType && key, ValueType && default_value) const
21804     {
21805         // value only works for objects
21806         if (JSON_HEDLEY_LIKELY(is_object()))
21807         {
21808             // if key is found, return value and given default value otherwise
21809             const auto it = find(std::forward<KeyType>(key));
21810             if (it != end())
21811             {
21812                 return it->template get<ReturnType>();
21813             }
21814 
21815             return std::forward<ValueType>(default_value);
21816         }
21817 
21818         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21819     }
21820 
21821     /// @brief access specified object element via JSON Pointer with default value
21822     /// @sa https://json.nlohmann.me/api/basic_json/value/
21823     template < class ValueType, detail::enable_if_t <
21824                    detail::is_getable<basic_json_t, ValueType>::value
21825                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21826     ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21827     {
21828         // value only works for objects
21829         if (JSON_HEDLEY_LIKELY(is_object()))
21830         {
21831             // if pointer resolves a value, return it or use default value
21832             JSON_TRY
21833             {
21834                 return ptr.get_checked(this).template get<ValueType>();
21835             }
21836             JSON_INTERNAL_CATCH (out_of_range&)
21837             {
21838                 return default_value;
21839             }
21840         }
21841 
21842         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21843     }
21844 
21845     /// @brief access specified object element via JSON Pointer with default value
21846     /// @sa https://json.nlohmann.me/api/basic_json/value/
21847     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21848                detail::enable_if_t <
21849                    detail::is_getable<basic_json_t, ReturnType>::value
21850                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21851     ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21852     {
21853         // value only works for objects
21854         if (JSON_HEDLEY_LIKELY(is_object()))
21855         {
21856             // if pointer resolves a value, return it or use default value
21857             JSON_TRY
21858             {
21859                 return ptr.get_checked(this).template get<ReturnType>();
21860             }
21861             JSON_INTERNAL_CATCH (out_of_range&)
21862             {
21863                 return std::forward<ValueType>(default_value);
21864             }
21865         }
21866 
21867         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21868     }
21869 
21870     template < class ValueType, class BasicJsonType, detail::enable_if_t <
21871                    detail::is_basic_json<BasicJsonType>::value
21872                    && detail::is_getable<basic_json_t, ValueType>::value
21873                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21874     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21875     ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21876     {
21877         return value(ptr.convert(), default_value);
21878     }
21879 
21880     template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21881                detail::enable_if_t <
21882                    detail::is_basic_json<BasicJsonType>::value
21883                    && detail::is_getable<basic_json_t, ReturnType>::value
21884                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21885     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21886     ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21887     {
21888         return value(ptr.convert(), std::forward<ValueType>(default_value));
21889     }
21890 
21891     /// @brief access the first element
21892     /// @sa https://json.nlohmann.me/api/basic_json/front/
21893     reference front()
21894     {
21895         return *begin();
21896     }
21897 
21898     /// @brief access the first element
21899     /// @sa https://json.nlohmann.me/api/basic_json/front/
21900     const_reference front() const
21901     {
21902         return *cbegin();
21903     }
21904 
21905     /// @brief access the last element
21906     /// @sa https://json.nlohmann.me/api/basic_json/back/
21907     reference back()
21908     {
21909         auto tmp = end();
21910         --tmp;
21911         return *tmp;
21912     }
21913 
21914     /// @brief access the last element
21915     /// @sa https://json.nlohmann.me/api/basic_json/back/
21916     const_reference back() const
21917     {
21918         auto tmp = cend();
21919         --tmp;
21920         return *tmp;
21921     }
21922 
21923     /// @brief remove element given an iterator
21924     /// @sa https://json.nlohmann.me/api/basic_json/erase/
21925     template < class IteratorType, detail::enable_if_t <
21926                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21927                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21928     IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
21929     {
21930         // make sure iterator fits the current value
21931         if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21932         {
21933             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21934         }
21935 
21936         IteratorType result = end();
21937 
21938         switch (m_data.m_type)
21939         {
21940             case value_t::boolean:
21941             case value_t::number_float:
21942             case value_t::number_integer:
21943             case value_t::number_unsigned:
21944             case value_t::string:
21945             case value_t::binary:
21946             {
21947                 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21948                 {
21949                     JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21950                 }
21951 
21952                 if (is_string())
21953                 {
21954                     AllocatorType<string_t> alloc;
21955                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21956                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21957                     m_data.m_value.string = nullptr;
21958                 }
21959                 else if (is_binary())
21960                 {
21961                     AllocatorType<binary_t> alloc;
21962                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21963                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21964                     m_data.m_value.binary = nullptr;
21965                 }
21966 
21967                 m_data.m_type = value_t::null;
21968                 assert_invariant();
21969                 break;
21970             }
21971 
21972             case value_t::object:
21973             {
21974                 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21975                 break;
21976             }
21977 
21978             case value_t::array:
21979             {
21980                 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21981                 break;
21982             }
21983 
21984             case value_t::null:
21985             case value_t::discarded:
21986             default:
21987                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21988         }
21989 
21990         return result;
21991     }
21992 
21993     /// @brief remove elements given an iterator range
21994     /// @sa https://json.nlohmann.me/api/basic_json/erase/
21995     template < class IteratorType, detail::enable_if_t <
21996                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21997                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21998     IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
21999     {
22000         // make sure iterator fits the current value
22001         if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22002         {
22003             JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22004         }
22005 
22006         IteratorType result = end();
22007 
22008         switch (m_data.m_type)
22009         {
22010             case value_t::boolean:
22011             case value_t::number_float:
22012             case value_t::number_integer:
22013             case value_t::number_unsigned:
22014             case value_t::string:
22015             case value_t::binary:
22016             {
22017                 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22018                                        || !last.m_it.primitive_iterator.is_end()))
22019                 {
22020                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22021                 }
22022 
22023                 if (is_string())
22024                 {
22025                     AllocatorType<string_t> alloc;
22026                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22027                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22028                     m_data.m_value.string = nullptr;
22029                 }
22030                 else if (is_binary())
22031                 {
22032                     AllocatorType<binary_t> alloc;
22033                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22034                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22035                     m_data.m_value.binary = nullptr;
22036                 }
22037 
22038                 m_data.m_type = value_t::null;
22039                 assert_invariant();
22040                 break;
22041             }
22042 
22043             case value_t::object:
22044             {
22045                 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22046                                               last.m_it.object_iterator);
22047                 break;
22048             }
22049 
22050             case value_t::array:
22051             {
22052                 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22053                                              last.m_it.array_iterator);
22054                 break;
22055             }
22056 
22057             case value_t::null:
22058             case value_t::discarded:
22059             default:
22060                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22061         }
22062 
22063         return result;
22064     }
22065 
22066   private:
22067     template < typename KeyType, detail::enable_if_t <
22068                    detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22069     size_type erase_internal(KeyType && key)
22070     {
22071         // this erase only works for objects
22072         if (JSON_HEDLEY_UNLIKELY(!is_object()))
22073         {
22074             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22075         }
22076 
22077         return m_data.m_value.object->erase(std::forward<KeyType>(key));
22078     }
22079 
22080     template < typename KeyType, detail::enable_if_t <
22081                    !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22082     size_type erase_internal(KeyType && key)
22083     {
22084         // this erase only works for objects
22085         if (JSON_HEDLEY_UNLIKELY(!is_object()))
22086         {
22087             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22088         }
22089 
22090         const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22091         if (it != m_data.m_value.object->end())
22092         {
22093             m_data.m_value.object->erase(it);
22094             return 1;
22095         }
22096         return 0;
22097     }
22098 
22099   public:
22100 
22101     /// @brief remove element from a JSON object given a key
22102     /// @sa https://json.nlohmann.me/api/basic_json/erase/
22103     size_type erase(const typename object_t::key_type& key)
22104     {
22105         // the indirection via erase_internal() is added to avoid making this
22106         // function a template and thus de-rank it during overload resolution
22107         return erase_internal(key);
22108     }
22109 
22110     /// @brief remove element from a JSON object given a key
22111     /// @sa https://json.nlohmann.me/api/basic_json/erase/
22112     template<class KeyType, detail::enable_if_t<
22113                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22114     size_type erase(KeyType && key)
22115     {
22116         return erase_internal(std::forward<KeyType>(key));
22117     }
22118 
22119     /// @brief remove element from a JSON array given an index
22120     /// @sa https://json.nlohmann.me/api/basic_json/erase/
22121     void erase(const size_type idx)
22122     {
22123         // this erase only works for arrays
22124         if (JSON_HEDLEY_LIKELY(is_array()))
22125         {
22126             if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22127             {
22128                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22129             }
22130 
22131             m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22132         }
22133         else
22134         {
22135             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22136         }
22137     }
22138 
22139     /// @}
22140 
22141     ////////////
22142     // lookup //
22143     ////////////
22144 
22145     /// @name lookup
22146     /// @{
22147 
22148     /// @brief find an element in a JSON object
22149     /// @sa https://json.nlohmann.me/api/basic_json/find/
22150     iterator find(const typename object_t::key_type& key)
22151     {
22152         auto result = end();
22153 
22154         if (is_object())
22155         {
22156             result.m_it.object_iterator = m_data.m_value.object->find(key);
22157         }
22158 
22159         return result;
22160     }
22161 
22162     /// @brief find an element in a JSON object
22163     /// @sa https://json.nlohmann.me/api/basic_json/find/
22164     const_iterator find(const typename object_t::key_type& key) const
22165     {
22166         auto result = cend();
22167 
22168         if (is_object())
22169         {
22170             result.m_it.object_iterator = m_data.m_value.object->find(key);
22171         }
22172 
22173         return result;
22174     }
22175 
22176     /// @brief find an element in a JSON object
22177     /// @sa https://json.nlohmann.me/api/basic_json/find/
22178     template<class KeyType, detail::enable_if_t<
22179                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22180     iterator find(KeyType && key)
22181     {
22182         auto result = end();
22183 
22184         if (is_object())
22185         {
22186             result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22187         }
22188 
22189         return result;
22190     }
22191 
22192     /// @brief find an element in a JSON object
22193     /// @sa https://json.nlohmann.me/api/basic_json/find/
22194     template<class KeyType, detail::enable_if_t<
22195                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22196     const_iterator find(KeyType && key) const
22197     {
22198         auto result = cend();
22199 
22200         if (is_object())
22201         {
22202             result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22203         }
22204 
22205         return result;
22206     }
22207 
22208     /// @brief returns the number of occurrences of a key in a JSON object
22209     /// @sa https://json.nlohmann.me/api/basic_json/count/
22210     size_type count(const typename object_t::key_type& key) const
22211     {
22212         // return 0 for all nonobject types
22213         return is_object() ? m_data.m_value.object->count(key) : 0;
22214     }
22215 
22216     /// @brief returns the number of occurrences of a key in a JSON object
22217     /// @sa https://json.nlohmann.me/api/basic_json/count/
22218     template<class KeyType, detail::enable_if_t<
22219                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22220     size_type count(KeyType && key) const
22221     {
22222         // return 0 for all nonobject types
22223         return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22224     }
22225 
22226     /// @brief check the existence of an element in a JSON object
22227     /// @sa https://json.nlohmann.me/api/basic_json/contains/
22228     bool contains(const typename object_t::key_type& key) const
22229     {
22230         return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22231     }
22232 
22233     /// @brief check the existence of an element in a JSON object
22234     /// @sa https://json.nlohmann.me/api/basic_json/contains/
22235     template<class KeyType, detail::enable_if_t<
22236                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22237     bool contains(KeyType && key) const
22238     {
22239         return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22240     }
22241 
22242     /// @brief check the existence of an element in a JSON object given a JSON pointer
22243     /// @sa https://json.nlohmann.me/api/basic_json/contains/
22244     bool contains(const json_pointer& ptr) const
22245     {
22246         return ptr.contains(this);
22247     }
22248 
22249     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22250     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22251     bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22252     {
22253         return ptr.contains(this);
22254     }
22255 
22256     /// @}
22257 
22258     ///////////////
22259     // iterators //
22260     ///////////////
22261 
22262     /// @name iterators
22263     /// @{
22264 
22265     /// @brief returns an iterator to the first element
22266     /// @sa https://json.nlohmann.me/api/basic_json/begin/
22267     iterator begin() noexcept
22268     {
22269         iterator result(this);
22270         result.set_begin();
22271         return result;
22272     }
22273 
22274     /// @brief returns an iterator to the first element
22275     /// @sa https://json.nlohmann.me/api/basic_json/begin/
22276     const_iterator begin() const noexcept
22277     {
22278         return cbegin();
22279     }
22280 
22281     /// @brief returns a const iterator to the first element
22282     /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
22283     const_iterator cbegin() const noexcept
22284     {
22285         const_iterator result(this);
22286         result.set_begin();
22287         return result;
22288     }
22289 
22290     /// @brief returns an iterator to one past the last element
22291     /// @sa https://json.nlohmann.me/api/basic_json/end/
22292     iterator end() noexcept
22293     {
22294         iterator result(this);
22295         result.set_end();
22296         return result;
22297     }
22298 
22299     /// @brief returns an iterator to one past the last element
22300     /// @sa https://json.nlohmann.me/api/basic_json/end/
22301     const_iterator end() const noexcept
22302     {
22303         return cend();
22304     }
22305 
22306     /// @brief returns an iterator to one past the last element
22307     /// @sa https://json.nlohmann.me/api/basic_json/cend/
22308     const_iterator cend() const noexcept
22309     {
22310         const_iterator result(this);
22311         result.set_end();
22312         return result;
22313     }
22314 
22315     /// @brief returns an iterator to the reverse-beginning
22316     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22317     reverse_iterator rbegin() noexcept
22318     {
22319         return reverse_iterator(end());
22320     }
22321 
22322     /// @brief returns an iterator to the reverse-beginning
22323     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22324     const_reverse_iterator rbegin() const noexcept
22325     {
22326         return crbegin();
22327     }
22328 
22329     /// @brief returns an iterator to the reverse-end
22330     /// @sa https://json.nlohmann.me/api/basic_json/rend/
22331     reverse_iterator rend() noexcept
22332     {
22333         return reverse_iterator(begin());
22334     }
22335 
22336     /// @brief returns an iterator to the reverse-end
22337     /// @sa https://json.nlohmann.me/api/basic_json/rend/
22338     const_reverse_iterator rend() const noexcept
22339     {
22340         return crend();
22341     }
22342 
22343     /// @brief returns a const reverse iterator to the last element
22344     /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
22345     const_reverse_iterator crbegin() const noexcept
22346     {
22347         return const_reverse_iterator(cend());
22348     }
22349 
22350     /// @brief returns a const reverse iterator to one before the first
22351     /// @sa https://json.nlohmann.me/api/basic_json/crend/
22352     const_reverse_iterator crend() const noexcept
22353     {
22354         return const_reverse_iterator(cbegin());
22355     }
22356 
22357   public:
22358     /// @brief wrapper to access iterator member functions in range-based for
22359     /// @sa https://json.nlohmann.me/api/basic_json/items/
22360     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22361     ///             version 4.0.0 of the library. Please use @ref items() instead;
22362     ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22363     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22364     static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22365     {
22366         return ref.items();
22367     }
22368 
22369     /// @brief wrapper to access iterator member functions in range-based for
22370     /// @sa https://json.nlohmann.me/api/basic_json/items/
22371     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22372     ///         version 4.0.0 of the library. Please use @ref items() instead;
22373     ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22374     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22375     static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22376     {
22377         return ref.items();
22378     }
22379 
22380     /// @brief helper to access iterator member functions in range-based for
22381     /// @sa https://json.nlohmann.me/api/basic_json/items/
22382     iteration_proxy<iterator> items() noexcept
22383     {
22384         return iteration_proxy<iterator>(*this);
22385     }
22386 
22387     /// @brief helper to access iterator member functions in range-based for
22388     /// @sa https://json.nlohmann.me/api/basic_json/items/
22389     iteration_proxy<const_iterator> items() const noexcept
22390     {
22391         return iteration_proxy<const_iterator>(*this);
22392     }
22393 
22394     /// @}
22395 
22396     //////////////
22397     // capacity //
22398     //////////////
22399 
22400     /// @name capacity
22401     /// @{
22402 
22403     /// @brief checks whether the container is empty.
22404     /// @sa https://json.nlohmann.me/api/basic_json/empty/
22405     bool empty() const noexcept
22406     {
22407         switch (m_data.m_type)
22408         {
22409             case value_t::null:
22410             {
22411                 // null values are empty
22412                 return true;
22413             }
22414 
22415             case value_t::array:
22416             {
22417                 // delegate call to array_t::empty()
22418                 return m_data.m_value.array->empty();
22419             }
22420 
22421             case value_t::object:
22422             {
22423                 // delegate call to object_t::empty()
22424                 return m_data.m_value.object->empty();
22425             }
22426 
22427             case value_t::string:
22428             case value_t::boolean:
22429             case value_t::number_integer:
22430             case value_t::number_unsigned:
22431             case value_t::number_float:
22432             case value_t::binary:
22433             case value_t::discarded:
22434             default:
22435             {
22436                 // all other types are nonempty
22437                 return false;
22438             }
22439         }
22440     }
22441 
22442     /// @brief returns the number of elements
22443     /// @sa https://json.nlohmann.me/api/basic_json/size/
22444     size_type size() const noexcept
22445     {
22446         switch (m_data.m_type)
22447         {
22448             case value_t::null:
22449             {
22450                 // null values are empty
22451                 return 0;
22452             }
22453 
22454             case value_t::array:
22455             {
22456                 // delegate call to array_t::size()
22457                 return m_data.m_value.array->size();
22458             }
22459 
22460             case value_t::object:
22461             {
22462                 // delegate call to object_t::size()
22463                 return m_data.m_value.object->size();
22464             }
22465 
22466             case value_t::string:
22467             case value_t::boolean:
22468             case value_t::number_integer:
22469             case value_t::number_unsigned:
22470             case value_t::number_float:
22471             case value_t::binary:
22472             case value_t::discarded:
22473             default:
22474             {
22475                 // all other types have size 1
22476                 return 1;
22477             }
22478         }
22479     }
22480 
22481     /// @brief returns the maximum possible number of elements
22482     /// @sa https://json.nlohmann.me/api/basic_json/max_size/
22483     size_type max_size() const noexcept
22484     {
22485         switch (m_data.m_type)
22486         {
22487             case value_t::array:
22488             {
22489                 // delegate call to array_t::max_size()
22490                 return m_data.m_value.array->max_size();
22491             }
22492 
22493             case value_t::object:
22494             {
22495                 // delegate call to object_t::max_size()
22496                 return m_data.m_value.object->max_size();
22497             }
22498 
22499             case value_t::null:
22500             case value_t::string:
22501             case value_t::boolean:
22502             case value_t::number_integer:
22503             case value_t::number_unsigned:
22504             case value_t::number_float:
22505             case value_t::binary:
22506             case value_t::discarded:
22507             default:
22508             {
22509                 // all other types have max_size() == size()
22510                 return size();
22511             }
22512         }
22513     }
22514 
22515     /// @}
22516 
22517     ///////////////
22518     // modifiers //
22519     ///////////////
22520 
22521     /// @name modifiers
22522     /// @{
22523 
22524     /// @brief clears the contents
22525     /// @sa https://json.nlohmann.me/api/basic_json/clear/
22526     void clear() noexcept
22527     {
22528         switch (m_data.m_type)
22529         {
22530             case value_t::number_integer:
22531             {
22532                 m_data.m_value.number_integer = 0;
22533                 break;
22534             }
22535 
22536             case value_t::number_unsigned:
22537             {
22538                 m_data.m_value.number_unsigned = 0;
22539                 break;
22540             }
22541 
22542             case value_t::number_float:
22543             {
22544                 m_data.m_value.number_float = 0.0;
22545                 break;
22546             }
22547 
22548             case value_t::boolean:
22549             {
22550                 m_data.m_value.boolean = false;
22551                 break;
22552             }
22553 
22554             case value_t::string:
22555             {
22556                 m_data.m_value.string->clear();
22557                 break;
22558             }
22559 
22560             case value_t::binary:
22561             {
22562                 m_data.m_value.binary->clear();
22563                 break;
22564             }
22565 
22566             case value_t::array:
22567             {
22568                 m_data.m_value.array->clear();
22569                 break;
22570             }
22571 
22572             case value_t::object:
22573             {
22574                 m_data.m_value.object->clear();
22575                 break;
22576             }
22577 
22578             case value_t::null:
22579             case value_t::discarded:
22580             default:
22581                 break;
22582         }
22583     }
22584 
22585     /// @brief add an object to an array
22586     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22587     void push_back(basic_json&& val)
22588     {
22589         // push_back only works for null objects or arrays
22590         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22591         {
22592             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22593         }
22594 
22595         // transform null object into an array
22596         if (is_null())
22597         {
22598             m_data.m_type = value_t::array;
22599             m_data.m_value = value_t::array;
22600             assert_invariant();
22601         }
22602 
22603         // add element to array (move semantics)
22604         const auto old_capacity = m_data.m_value.array->capacity();
22605         m_data.m_value.array->push_back(std::move(val));
22606         set_parent(m_data.m_value.array->back(), old_capacity);
22607         // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22608     }
22609 
22610     /// @brief add an object to an array
22611     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22612     reference operator+=(basic_json&& val)
22613     {
22614         push_back(std::move(val));
22615         return *this;
22616     }
22617 
22618     /// @brief add an object to an array
22619     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22620     void push_back(const basic_json& val)
22621     {
22622         // push_back only works for null objects or arrays
22623         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22624         {
22625             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22626         }
22627 
22628         // transform null object into an array
22629         if (is_null())
22630         {
22631             m_data.m_type = value_t::array;
22632             m_data.m_value = value_t::array;
22633             assert_invariant();
22634         }
22635 
22636         // add element to array
22637         const auto old_capacity = m_data.m_value.array->capacity();
22638         m_data.m_value.array->push_back(val);
22639         set_parent(m_data.m_value.array->back(), old_capacity);
22640     }
22641 
22642     /// @brief add an object to an array
22643     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22644     reference operator+=(const basic_json& val)
22645     {
22646         push_back(val);
22647         return *this;
22648     }
22649 
22650     /// @brief add an object to an object
22651     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22652     void push_back(const typename object_t::value_type& val)
22653     {
22654         // push_back only works for null objects or objects
22655         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22656         {
22657             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22658         }
22659 
22660         // transform null object into an object
22661         if (is_null())
22662         {
22663             m_data.m_type = value_t::object;
22664             m_data.m_value = value_t::object;
22665             assert_invariant();
22666         }
22667 
22668         // add element to object
22669         auto res = m_data.m_value.object->insert(val);
22670         set_parent(res.first->second);
22671     }
22672 
22673     /// @brief add an object to an object
22674     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22675     reference operator+=(const typename object_t::value_type& val)
22676     {
22677         push_back(val);
22678         return *this;
22679     }
22680 
22681     /// @brief add an object to an object
22682     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
22683     void push_back(initializer_list_t init)
22684     {
22685         if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22686         {
22687             basic_json&& key = init.begin()->moved_or_copied();
22688             push_back(typename object_t::value_type(
22689                           std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22690         }
22691         else
22692         {
22693             push_back(basic_json(init));
22694         }
22695     }
22696 
22697     /// @brief add an object to an object
22698     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
22699     reference operator+=(initializer_list_t init)
22700     {
22701         push_back(init);
22702         return *this;
22703     }
22704 
22705     /// @brief add an object to an array
22706     /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
22707     template<class... Args>
22708     reference emplace_back(Args&& ... args)
22709     {
22710         // emplace_back only works for null objects or arrays
22711         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22712         {
22713             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22714         }
22715 
22716         // transform null object into an array
22717         if (is_null())
22718         {
22719             m_data.m_type = value_t::array;
22720             m_data.m_value = value_t::array;
22721             assert_invariant();
22722         }
22723 
22724         // add element to array (perfect forwarding)
22725         const auto old_capacity = m_data.m_value.array->capacity();
22726         m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22727         return set_parent(m_data.m_value.array->back(), old_capacity);
22728     }
22729 
22730     /// @brief add an object to an object if key does not exist
22731     /// @sa https://json.nlohmann.me/api/basic_json/emplace/
22732     template<class... Args>
22733     std::pair<iterator, bool> emplace(Args&& ... args)
22734     {
22735         // emplace only works for null objects or arrays
22736         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22737         {
22738             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22739         }
22740 
22741         // transform null object into an object
22742         if (is_null())
22743         {
22744             m_data.m_type = value_t::object;
22745             m_data.m_value = value_t::object;
22746             assert_invariant();
22747         }
22748 
22749         // add element to array (perfect forwarding)
22750         auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22751         set_parent(res.first->second);
22752 
22753         // create result iterator and set iterator to the result of emplace
22754         auto it = begin();
22755         it.m_it.object_iterator = res.first;
22756 
22757         // return pair of iterator and boolean
22758         return {it, res.second};
22759     }
22760 
22761     /// Helper for insertion of an iterator
22762     /// @note: This uses std::distance to support GCC 4.8,
22763     ///        see https://github.com/nlohmann/json/pull/1257
22764     template<typename... Args>
22765     iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
22766     {
22767         iterator result(this);
22768         JSON_ASSERT(m_data.m_value.array != nullptr);
22769 
22770         auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22771         m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22772         result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22773 
22774         // This could have been written as:
22775         // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22776         // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22777 
22778         set_parents();
22779         return result;
22780     }
22781 
22782     /// @brief inserts element into array
22783     /// @sa https://json.nlohmann.me/api/basic_json/insert/
22784     iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
22785     {
22786         // insert only works for arrays
22787         if (JSON_HEDLEY_LIKELY(is_array()))
22788         {
22789             // check if iterator pos fits to this JSON value
22790             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22791             {
22792                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22793             }
22794 
22795             // insert to array and return iterator
22796             return insert_iterator(pos, val);
22797         }
22798 
22799         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22800     }
22801 
22802     /// @brief inserts element into array
22803     /// @sa https://json.nlohmann.me/api/basic_json/insert/
22804     iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
22805     {
22806         return insert(pos, val);
22807     }
22808 
22809     /// @brief inserts copies of element into array
22810     /// @sa https://json.nlohmann.me/api/basic_json/insert/
22811     iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
22812     {
22813         // insert only works for arrays
22814         if (JSON_HEDLEY_LIKELY(is_array()))
22815         {
22816             // check if iterator pos fits to this JSON value
22817             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22818             {
22819                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22820             }
22821 
22822             // insert to array and return iterator
22823             return insert_iterator(pos, cnt, val);
22824         }
22825 
22826         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22827     }
22828 
22829     /// @brief inserts range of elements into array
22830     /// @sa https://json.nlohmann.me/api/basic_json/insert/
22831     iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
22832     {
22833         // insert only works for arrays
22834         if (JSON_HEDLEY_UNLIKELY(!is_array()))
22835         {
22836             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22837         }
22838 
22839         // check if iterator pos fits to this JSON value
22840         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22841         {
22842             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22843         }
22844 
22845         // check if range iterators belong to the same JSON object
22846         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22847         {
22848             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22849         }
22850 
22851         if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22852         {
22853             JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22854         }
22855 
22856         // insert to array and return iterator
22857         return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22858     }
22859 
22860     /// @brief inserts elements from initializer list into array
22861     /// @sa https://json.nlohmann.me/api/basic_json/insert/
22862     iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
22863     {
22864         // insert only works for arrays
22865         if (JSON_HEDLEY_UNLIKELY(!is_array()))
22866         {
22867             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22868         }
22869 
22870         // check if iterator pos fits to this JSON value
22871         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22872         {
22873             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22874         }
22875 
22876         // insert to array and return iterator
22877         return insert_iterator(pos, ilist.begin(), ilist.end());
22878     }
22879 
22880     /// @brief inserts range of elements into object
22881     /// @sa https://json.nlohmann.me/api/basic_json/insert/
22882     void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
22883     {
22884         // insert only works for objects
22885         if (JSON_HEDLEY_UNLIKELY(!is_object()))
22886         {
22887             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22888         }
22889 
22890         // check if range iterators belong to the same JSON object
22891         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22892         {
22893             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22894         }
22895 
22896         // passed iterators must belong to objects
22897         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22898         {
22899             JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22900         }
22901 
22902         m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22903     }
22904 
22905     /// @brief updates a JSON object from another object, overwriting existing keys
22906     /// @sa https://json.nlohmann.me/api/basic_json/update/
22907     void update(const_reference j, bool merge_objects = false)
22908     {
22909         update(j.begin(), j.end(), merge_objects);
22910     }
22911 
22912     /// @brief updates a JSON object from another object, overwriting existing keys
22913     /// @sa https://json.nlohmann.me/api/basic_json/update/
22914     void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
22915     {
22916         // implicitly convert null value to an empty object
22917         if (is_null())
22918         {
22919             m_data.m_type = value_t::object;
22920             m_data.m_value.object = create<object_t>();
22921             assert_invariant();
22922         }
22923 
22924         if (JSON_HEDLEY_UNLIKELY(!is_object()))
22925         {
22926             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22927         }
22928 
22929         // check if range iterators belong to the same JSON object
22930         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22931         {
22932             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22933         }
22934 
22935         // passed iterators must belong to objects
22936         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22937         {
22938             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22939         }
22940 
22941         for (auto it = first; it != last; ++it)
22942         {
22943             if (merge_objects && it.value().is_object())
22944             {
22945                 auto it2 = m_data.m_value.object->find(it.key());
22946                 if (it2 != m_data.m_value.object->end())
22947                 {
22948                     it2->second.update(it.value(), true);
22949                     continue;
22950                 }
22951             }
22952             m_data.m_value.object->operator[](it.key()) = it.value();
22953 #if JSON_DIAGNOSTICS
22954             m_data.m_value.object->operator[](it.key()).m_parent = this;
22955 #endif
22956         }
22957     }
22958 
22959     /// @brief exchanges the values
22960     /// @sa https://json.nlohmann.me/api/basic_json/swap/
22961     void swap(reference other) noexcept (
22962         std::is_nothrow_move_constructible<value_t>::value&&
22963         std::is_nothrow_move_assignable<value_t>::value&&
22964         std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22965         std::is_nothrow_move_assignable<json_value>::value
22966     )
22967     {
22968         std::swap(m_data.m_type, other.m_data.m_type);
22969         std::swap(m_data.m_value, other.m_data.m_value);
22970 
22971         set_parents();
22972         other.set_parents();
22973         assert_invariant();
22974     }
22975 
22976     /// @brief exchanges the values
22977     /// @sa https://json.nlohmann.me/api/basic_json/swap/
22978     friend void swap(reference left, reference right) noexcept (
22979         std::is_nothrow_move_constructible<value_t>::value&&
22980         std::is_nothrow_move_assignable<value_t>::value&&
22981         std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22982         std::is_nothrow_move_assignable<json_value>::value
22983     )
22984     {
22985         left.swap(right);
22986     }
22987 
22988     /// @brief exchanges the values
22989     /// @sa https://json.nlohmann.me/api/basic_json/swap/
22990     void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22991     {
22992         // swap only works for arrays
22993         if (JSON_HEDLEY_LIKELY(is_array()))
22994         {
22995             using std::swap;
22996             swap(*(m_data.m_value.array), other);
22997         }
22998         else
22999         {
23000             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23001         }
23002     }
23003 
23004     /// @brief exchanges the values
23005     /// @sa https://json.nlohmann.me/api/basic_json/swap/
23006     void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23007     {
23008         // swap only works for objects
23009         if (JSON_HEDLEY_LIKELY(is_object()))
23010         {
23011             using std::swap;
23012             swap(*(m_data.m_value.object), other);
23013         }
23014         else
23015         {
23016             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23017         }
23018     }
23019 
23020     /// @brief exchanges the values
23021     /// @sa https://json.nlohmann.me/api/basic_json/swap/
23022     void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23023     {
23024         // swap only works for strings
23025         if (JSON_HEDLEY_LIKELY(is_string()))
23026         {
23027             using std::swap;
23028             swap(*(m_data.m_value.string), other);
23029         }
23030         else
23031         {
23032             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23033         }
23034     }
23035 
23036     /// @brief exchanges the values
23037     /// @sa https://json.nlohmann.me/api/basic_json/swap/
23038     void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23039     {
23040         // swap only works for strings
23041         if (JSON_HEDLEY_LIKELY(is_binary()))
23042         {
23043             using std::swap;
23044             swap(*(m_data.m_value.binary), other);
23045         }
23046         else
23047         {
23048             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23049         }
23050     }
23051 
23052     /// @brief exchanges the values
23053     /// @sa https://json.nlohmann.me/api/basic_json/swap/
23054     void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23055     {
23056         // swap only works for strings
23057         if (JSON_HEDLEY_LIKELY(is_binary()))
23058         {
23059             using std::swap;
23060             swap(*(m_data.m_value.binary), other);
23061         }
23062         else
23063         {
23064             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23065         }
23066     }
23067 
23068     /// @}
23069 
23070     //////////////////////////////////////////
23071     // lexicographical comparison operators //
23072     //////////////////////////////////////////
23073 
23074     /// @name lexicographical comparison operators
23075     /// @{
23076 
23077     // note parentheses around operands are necessary; see
23078     // https://github.com/nlohmann/json/issues/1530
23079 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \ 
23080     const auto lhs_type = lhs.type();                                                                    \ 
23081     const auto rhs_type = rhs.type();                                                                    \ 
23082     \ 
23083     if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \ 
23084     {                                                                                                    \ 
23085         switch (lhs_type)                                                                                \ 
23086         {                                                                                                \ 
23087             case value_t::array:                                                                         \ 
23088                 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array);                                     \ 
23089                 \ 
23090             case value_t::object:                                                                        \ 
23091                 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object);                                   \ 
23092                 \ 
23093             case value_t::null:                                                                          \ 
23094                 return (null_result);                                                                    \ 
23095                 \ 
23096             case value_t::string:                                                                        \ 
23097                 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string);                                   \ 
23098                 \ 
23099             case value_t::boolean:                                                                       \ 
23100                 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean);                                   \ 
23101                 \ 
23102             case value_t::number_integer:                                                                \ 
23103                 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer);                     \ 
23104                 \ 
23105             case value_t::number_unsigned:                                                               \ 
23106                 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned);                   \ 
23107                 \ 
23108             case value_t::number_float:                                                                  \ 
23109                 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float);                         \ 
23110                 \ 
23111             case value_t::binary:                                                                        \ 
23112                 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary);                                   \ 
23113                 \ 
23114             case value_t::discarded:                                                                     \ 
23115             default:                                                                                     \ 
23116                 return (unordered_result);                                                               \ 
23117         }                                                                                                \ 
23118     }                                                                                                    \ 
23119     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \ 
23120     {                                                                                                    \ 
23121         return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float;      \ 
23122     }                                                                                                    \ 
23123     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \ 
23124     {                                                                                                    \ 
23125         return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer);      \ 
23126     }                                                                                                    \ 
23127     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \ 
23128     {                                                                                                    \ 
23129         return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float;     \ 
23130     }                                                                                                    \ 
23131     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \ 
23132     {                                                                                                    \ 
23133         return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned);     \ 
23134     }                                                                                                    \ 
23135     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \ 
23136     {                                                                                                    \ 
23137         return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ 
23138     }                                                                                                    \ 
23139     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \ 
23140     {                                                                                                    \ 
23141         return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \ 
23142     }                                                                                                    \ 
23143     else if(compares_unordered(lhs, rhs))\ 
23144     {\ 
23145         return (unordered_result);\ 
23146     }\ 
23147     \ 
23148     return (default_result);
23149 
23150   JSON_PRIVATE_UNLESS_TESTED:
23151     // returns true if:
23152     // - any operand is NaN and the other operand is of number type
23153     // - any operand is discarded
23154     // in legacy mode, discarded values are considered ordered if
23155     // an operation is computed as an odd number of inverses of others
23156     static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23157     {
23158         if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23159                 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23160         {
23161             return true;
23162         }
23163 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23164         return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23165 #else
23166         static_cast<void>(inverse);
23167         return lhs.is_discarded() || rhs.is_discarded();
23168 #endif
23169     }
23170 
23171   private:
23172     bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23173     {
23174         return compares_unordered(*this, rhs, inverse);
23175     }
23176 
23177   public:
23178 #if JSON_HAS_THREE_WAY_COMPARISON
23179     /// @brief comparison: equal
23180     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23181     bool operator==(const_reference rhs) const noexcept
23182     {
23183 #ifdef __GNUC__
23184 #pragma GCC diagnostic push
23185 #pragma GCC diagnostic ignored "-Wfloat-equal"
23186 #endif
23187         const_reference lhs = *this;
23188         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23189 #ifdef __GNUC__
23190 #pragma GCC diagnostic pop
23191 #endif
23192     }
23193 
23194     /// @brief comparison: equal
23195     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23196     template<typename ScalarType>
23197     requires std::is_scalar_v<ScalarType>
23198     bool operator==(ScalarType rhs) const noexcept
23199     {
23200         return *this == basic_json(rhs);
23201     }
23202 
23203     /// @brief comparison: not equal
23204     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23205     bool operator!=(const_reference rhs) const noexcept
23206     {
23207         if (compares_unordered(rhs, true))
23208         {
23209             return false;
23210         }
23211         return !operator==(rhs);
23212     }
23213 
23214     /// @brief comparison: 3-way
23215     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23216     std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23217     {
23218         const_reference lhs = *this;
23219         // default_result is used if we cannot compare values. In that case,
23220         // we compare types.
23221         JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23222                                 std::partial_ordering::equivalent,
23223                                 std::partial_ordering::unordered,
23224                                 lhs_type <=> rhs_type) // *NOPAD*
23225     }
23226 
23227     /// @brief comparison: 3-way
23228     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23229     template<typename ScalarType>
23230     requires std::is_scalar_v<ScalarType>
23231     std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23232     {
23233         return *this <=> basic_json(rhs); // *NOPAD*
23234     }
23235 
23236 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23237     // all operators that are computed as an odd number of inverses of others
23238     // need to be overloaded to emulate the legacy comparison behavior
23239 
23240     /// @brief comparison: less than or equal
23241     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23242     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23243     bool operator<=(const_reference rhs) const noexcept
23244     {
23245         if (compares_unordered(rhs, true))
23246         {
23247             return false;
23248         }
23249         return !(rhs < *this);
23250     }
23251 
23252     /// @brief comparison: less than or equal
23253     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23254     template<typename ScalarType>
23255     requires std::is_scalar_v<ScalarType>
23256     bool operator<=(ScalarType rhs) const noexcept
23257     {
23258         return *this <= basic_json(rhs);
23259     }
23260 
23261     /// @brief comparison: greater than or equal
23262     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23263     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23264     bool operator>=(const_reference rhs) const noexcept
23265     {
23266         if (compares_unordered(rhs, true))
23267         {
23268             return false;
23269         }
23270         return !(*this < rhs);
23271     }
23272 
23273     /// @brief comparison: greater than or equal
23274     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23275     template<typename ScalarType>
23276     requires std::is_scalar_v<ScalarType>
23277     bool operator>=(ScalarType rhs) const noexcept
23278     {
23279         return *this >= basic_json(rhs);
23280     }
23281 #endif
23282 #else
23283     /// @brief comparison: equal
23284     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23285     friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23286     {
23287 #ifdef __GNUC__
23288 #pragma GCC diagnostic push
23289 #pragma GCC diagnostic ignored "-Wfloat-equal"
23290 #endif
23291         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23292 #ifdef __GNUC__
23293 #pragma GCC diagnostic pop
23294 #endif
23295     }
23296 
23297     /// @brief comparison: equal
23298     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23299     template<typename ScalarType, typename std::enable_if<
23300                  std::is_scalar<ScalarType>::value, int>::type = 0>
23301     friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23302     {
23303         return lhs == basic_json(rhs);
23304     }
23305 
23306     /// @brief comparison: equal
23307     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23308     template<typename ScalarType, typename std::enable_if<
23309                  std::is_scalar<ScalarType>::value, int>::type = 0>
23310     friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23311     {
23312         return basic_json(lhs) == rhs;
23313     }
23314 
23315     /// @brief comparison: not equal
23316     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23317     friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23318     {
23319         if (compares_unordered(lhs, rhs, true))
23320         {
23321             return false;
23322         }
23323         return !(lhs == rhs);
23324     }
23325 
23326     /// @brief comparison: not equal
23327     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23328     template<typename ScalarType, typename std::enable_if<
23329                  std::is_scalar<ScalarType>::value, int>::type = 0>
23330     friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23331     {
23332         return lhs != basic_json(rhs);
23333     }
23334 
23335     /// @brief comparison: not equal
23336     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23337     template<typename ScalarType, typename std::enable_if<
23338                  std::is_scalar<ScalarType>::value, int>::type = 0>
23339     friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23340     {
23341         return basic_json(lhs) != rhs;
23342     }
23343 
23344     /// @brief comparison: less than
23345     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23346     friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23347     {
23348         // default_result is used if we cannot compare values. In that case,
23349         // we compare types. Note we have to call the operator explicitly,
23350         // because MSVC has problems otherwise.
23351         JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23352     }
23353 
23354     /// @brief comparison: less than
23355     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23356     template<typename ScalarType, typename std::enable_if<
23357                  std::is_scalar<ScalarType>::value, int>::type = 0>
23358     friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23359     {
23360         return lhs < basic_json(rhs);
23361     }
23362 
23363     /// @brief comparison: less than
23364     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23365     template<typename ScalarType, typename std::enable_if<
23366                  std::is_scalar<ScalarType>::value, int>::type = 0>
23367     friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23368     {
23369         return basic_json(lhs) < rhs;
23370     }
23371 
23372     /// @brief comparison: less than or equal
23373     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23374     friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23375     {
23376         if (compares_unordered(lhs, rhs, true))
23377         {
23378             return false;
23379         }
23380         return !(rhs < lhs);
23381     }
23382 
23383     /// @brief comparison: less than or equal
23384     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23385     template<typename ScalarType, typename std::enable_if<
23386                  std::is_scalar<ScalarType>::value, int>::type = 0>
23387     friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23388     {
23389         return lhs <= basic_json(rhs);
23390     }
23391 
23392     /// @brief comparison: less than or equal
23393     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23394     template<typename ScalarType, typename std::enable_if<
23395                  std::is_scalar<ScalarType>::value, int>::type = 0>
23396     friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23397     {
23398         return basic_json(lhs) <= rhs;
23399     }
23400 
23401     /// @brief comparison: greater than
23402     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23403     friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23404     {
23405         // double inverse
23406         if (compares_unordered(lhs, rhs))
23407         {
23408             return false;
23409         }
23410         return !(lhs <= rhs);
23411     }
23412 
23413     /// @brief comparison: greater than
23414     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23415     template<typename ScalarType, typename std::enable_if<
23416                  std::is_scalar<ScalarType>::value, int>::type = 0>
23417     friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23418     {
23419         return lhs > basic_json(rhs);
23420     }
23421 
23422     /// @brief comparison: greater than
23423     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23424     template<typename ScalarType, typename std::enable_if<
23425                  std::is_scalar<ScalarType>::value, int>::type = 0>
23426     friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23427     {
23428         return basic_json(lhs) > rhs;
23429     }
23430 
23431     /// @brief comparison: greater than or equal
23432     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23433     friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23434     {
23435         if (compares_unordered(lhs, rhs, true))
23436         {
23437             return false;
23438         }
23439         return !(lhs < rhs);
23440     }
23441 
23442     /// @brief comparison: greater than or equal
23443     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23444     template<typename ScalarType, typename std::enable_if<
23445                  std::is_scalar<ScalarType>::value, int>::type = 0>
23446     friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23447     {
23448         return lhs >= basic_json(rhs);
23449     }
23450 
23451     /// @brief comparison: greater than or equal
23452     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23453     template<typename ScalarType, typename std::enable_if<
23454                  std::is_scalar<ScalarType>::value, int>::type = 0>
23455     friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23456     {
23457         return basic_json(lhs) >= rhs;
23458     }
23459 #endif
23460 
23461 #undef JSON_IMPLEMENT_OPERATOR
23462 
23463     /// @}
23464 
23465     ///////////////////
23466     // serialization //
23467     ///////////////////
23468 
23469     /// @name serialization
23470     /// @{
23471 #ifndef JSON_NO_IO
23472     /// @brief serialize to stream
23473     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23474     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23475     {
23476         // read width member and use it as indentation parameter if nonzero
23477         const bool pretty_print = o.width() > 0;
23478         const auto indentation = pretty_print ? o.width() : 0;
23479 
23480         // reset width to 0 for subsequent calls to this stream
23481         o.width(0);
23482 
23483         // do the actual serialization
23484         serializer s(detail::output_adapter<char>(o), o.fill());
23485         s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23486         return o;
23487     }
23488 
23489     /// @brief serialize to stream
23490     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
23491     /// @deprecated This function is deprecated since 3.0.0 and will be removed in
23492     ///             version 4.0.0 of the library. Please use
23493     ///             operator<<(std::ostream&, const basic_json&) instead; that is,
23494     ///             replace calls like `j >> o;` with `o << j;`.
23495     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23496     friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23497     {
23498         return o << j;
23499     }
23500 #endif  // JSON_NO_IO
23501     /// @}
23502 
23503     /////////////////////
23504     // deserialization //
23505     /////////////////////
23506 
23507     /// @name deserialization
23508     /// @{
23509 
23510     /// @brief deserialize from a compatible input
23511     /// @sa https://json.nlohmann.me/api/basic_json/parse/
23512     template<typename InputType>
23513     JSON_HEDLEY_WARN_UNUSED_RESULT
23514     static basic_json parse(InputType&& i,
23515                             parser_callback_t cb = nullptr,
23516                             const bool allow_exceptions = true,
23517                             const bool ignore_comments = false)
23518     {
23519         basic_json result;
23520         parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23521         return result;
23522     }
23523 
23524     /// @brief deserialize from a pair of character iterators
23525     /// @sa https://json.nlohmann.me/api/basic_json/parse/
23526     template<typename IteratorType>
23527     JSON_HEDLEY_WARN_UNUSED_RESULT
23528     static basic_json parse(IteratorType first,
23529                             IteratorType last,
23530                             parser_callback_t cb = nullptr,
23531                             const bool allow_exceptions = true,
23532                             const bool ignore_comments = false)
23533     {
23534         basic_json result;
23535         parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23536         return result;
23537     }
23538 
23539     JSON_HEDLEY_WARN_UNUSED_RESULT
23540     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23541     static basic_json parse(detail::span_input_adapter&& i,
23542                             parser_callback_t cb = nullptr,
23543                             const bool allow_exceptions = true,
23544                             const bool ignore_comments = false)
23545     {
23546         basic_json result;
23547         parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result);
23548         return result;
23549     }
23550 
23551     /// @brief check if the input is valid JSON
23552     /// @sa https://json.nlohmann.me/api/basic_json/accept/
23553     template<typename InputType>
23554     static bool accept(InputType&& i,
23555                        const bool ignore_comments = false)
23556     {
23557         return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23558     }
23559 
23560     /// @brief check if the input is valid JSON
23561     /// @sa https://json.nlohmann.me/api/basic_json/accept/
23562     template<typename IteratorType>
23563     static bool accept(IteratorType first, IteratorType last,
23564                        const bool ignore_comments = false)
23565     {
23566         return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23567     }
23568 
23569     JSON_HEDLEY_WARN_UNUSED_RESULT
23570     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23571     static bool accept(detail::span_input_adapter&& i,
23572                        const bool ignore_comments = false)
23573     {
23574         return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23575     }
23576 
23577     /// @brief generate SAX events
23578     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23579     template <typename InputType, typename SAX>
23580     JSON_HEDLEY_NON_NULL(2)
23581     static bool sax_parse(InputType&& i, SAX* sax,
23582                           input_format_t format = input_format_t::json,
23583                           const bool strict = true,
23584                           const bool ignore_comments = false)
23585     {
23586         auto ia = detail::input_adapter(std::forward<InputType>(i));
23587         return format == input_format_t::json
23588                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23589                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23590     }
23591 
23592     /// @brief generate SAX events
23593     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23594     template<class IteratorType, class SAX>
23595     JSON_HEDLEY_NON_NULL(3)
23596     static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23597                           input_format_t format = input_format_t::json,
23598                           const bool strict = true,
23599                           const bool ignore_comments = false)
23600     {
23601         auto ia = detail::input_adapter(std::move(first), std::move(last));
23602         return format == input_format_t::json
23603                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23604                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23605     }
23606 
23607     /// @brief generate SAX events
23608     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
23609     /// @deprecated This function is deprecated since 3.8.0 and will be removed in
23610     ///             version 4.0.0 of the library. Please use
23611     ///             sax_parse(ptr, ptr + len) instead.
23612     template <typename SAX>
23613     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23614     JSON_HEDLEY_NON_NULL(2)
23615     static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23616                           input_format_t format = input_format_t::json,
23617                           const bool strict = true,
23618                           const bool ignore_comments = false)
23619     {
23620         auto ia = i.get();
23621         return format == input_format_t::json
23622                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23623                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23624                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23625                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23626     }
23627 #ifndef JSON_NO_IO
23628     /// @brief deserialize from stream
23629     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23630     /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
23631     ///             version 4.0.0 of the library. Please use
23632     ///             operator>>(std::istream&, basic_json&) instead; that is,
23633     ///             replace calls like `j << i;` with `i >> j;`.
23634     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23635     friend std::istream& operator<<(basic_json& j, std::istream& i)
23636     {
23637         return operator>>(i, j);
23638     }
23639 
23640     /// @brief deserialize from stream
23641     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
23642     friend std::istream& operator>>(std::istream& i, basic_json& j)
23643     {
23644         parser(detail::input_adapter(i)).parse(false, j);
23645         return i;
23646     }
23647 #endif  // JSON_NO_IO
23648     /// @}
23649 
23650     ///////////////////////////
23651     // convenience functions //
23652     ///////////////////////////
23653 
23654     /// @brief return the type as string
23655     /// @sa https://json.nlohmann.me/api/basic_json/type_name/
23656     JSON_HEDLEY_RETURNS_NON_NULL
23657     const char* type_name() const noexcept
23658     {
23659         switch (m_data.m_type)
23660         {
23661             case value_t::null:
23662                 return "null";
23663             case value_t::object:
23664                 return "object";
23665             case value_t::array:
23666                 return "array";
23667             case value_t::string:
23668                 return "string";
23669             case value_t::boolean:
23670                 return "boolean";
23671             case value_t::binary:
23672                 return "binary";
23673             case value_t::discarded:
23674                 return "discarded";
23675             case value_t::number_integer:
23676             case value_t::number_unsigned:
23677             case value_t::number_float:
23678             default:
23679                 return "number";
23680         }
23681     }
23682 
23683   JSON_PRIVATE_UNLESS_TESTED:
23684     //////////////////////
23685     // member variables //
23686     //////////////////////
23687 
23688     struct data
23689     {
23690         /// the type of the current element
23691         value_t m_type = value_t::null;
23692 
23693         /// the value of the current element
23694         json_value m_value = {};
23695 
23696         data(const value_t v)
23697             : m_type(v), m_value(v)
23698         {
23699         }
23700 
23701         data(size_type cnt, const basic_json& val)
23702             : m_type(value_t::array)
23703         {
23704             m_value.array = create<array_t>(cnt, val);
23705         }
23706 
23707         data() noexcept = default;
23708         data(data&&) noexcept = default;
23709         data(const data&) noexcept = delete;
23710         data& operator=(data&&) noexcept = delete;
23711         data& operator=(const data&) noexcept = delete;
23712 
23713         ~data() noexcept
23714         {
23715             m_value.destroy(m_type);
23716         }
23717     };
23718 
23719     data m_data = {};
23720 
23721 #if JSON_DIAGNOSTICS
23722     /// a pointer to a parent value (for debugging purposes)
23723     basic_json* m_parent = nullptr;
23724 #endif
23725 
23726     //////////////////////////////////////////
23727     // binary serialization/deserialization //
23728     //////////////////////////////////////////
23729 
23730     /// @name binary serialization/deserialization support
23731     /// @{
23732 
23733   public:
23734     /// @brief create a CBOR serialization of a given JSON value
23735     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23736     static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23737     {
23738         std::vector<std::uint8_t> result;
23739         to_cbor(j, result);
23740         return result;
23741     }
23742 
23743     /// @brief create a CBOR serialization of a given JSON value
23744     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23745     static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23746     {
23747         binary_writer<std::uint8_t>(o).write_cbor(j);
23748     }
23749 
23750     /// @brief create a CBOR serialization of a given JSON value
23751     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
23752     static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
23753     {
23754         binary_writer<char>(o).write_cbor(j);
23755     }
23756 
23757     /// @brief create a MessagePack serialization of a given JSON value
23758     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23759     static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23760     {
23761         std::vector<std::uint8_t> result;
23762         to_msgpack(j, result);
23763         return result;
23764     }
23765 
23766     /// @brief create a MessagePack serialization of a given JSON value
23767     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23768     static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23769     {
23770         binary_writer<std::uint8_t>(o).write_msgpack(j);
23771     }
23772 
23773     /// @brief create a MessagePack serialization of a given JSON value
23774     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
23775     static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
23776     {
23777         binary_writer<char>(o).write_msgpack(j);
23778     }
23779 
23780     /// @brief create a UBJSON serialization of a given JSON value
23781     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23782     static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23783             const bool use_size = false,
23784             const bool use_type = false)
23785     {
23786         std::vector<std::uint8_t> result;
23787         to_ubjson(j, result, use_size, use_type);
23788         return result;
23789     }
23790 
23791     /// @brief create a UBJSON serialization of a given JSON value
23792     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23793     static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23794                           const bool use_size = false, const bool use_type = false)
23795     {
23796         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23797     }
23798 
23799     /// @brief create a UBJSON serialization of a given JSON value
23800     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
23801     static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
23802                           const bool use_size = false, const bool use_type = false)
23803     {
23804         binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23805     }
23806 
23807     /// @brief create a BJData serialization of a given JSON value
23808     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23809     static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23810             const bool use_size = false,
23811             const bool use_type = false)
23812     {
23813         std::vector<std::uint8_t> result;
23814         to_bjdata(j, result, use_size, use_type);
23815         return result;
23816     }
23817 
23818     /// @brief create a BJData serialization of a given JSON value
23819     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23820     static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
23821                           const bool use_size = false, const bool use_type = false)
23822     {
23823         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23824     }
23825 
23826     /// @brief create a BJData serialization of a given JSON value
23827     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
23828     static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
23829                           const bool use_size = false, const bool use_type = false)
23830     {
23831         binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23832     }
23833 
23834     /// @brief create a BSON serialization of a given JSON value
23835     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23836     static std::vector<std::uint8_t> to_bson(const basic_json& j)
23837     {
23838         std::vector<std::uint8_t> result;
23839         to_bson(j, result);
23840         return result;
23841     }
23842 
23843     /// @brief create a BSON serialization of a given JSON value
23844     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23845     static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
23846     {
23847         binary_writer<std::uint8_t>(o).write_bson(j);
23848     }
23849 
23850     /// @brief create a BSON serialization of a given JSON value
23851     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
23852     static void to_bson(const basic_json& j, detail::output_adapter<char> o)
23853     {
23854         binary_writer<char>(o).write_bson(j);
23855     }
23856 
23857     /// @brief create a JSON value from an input in CBOR format
23858     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23859     template<typename InputType>
23860     JSON_HEDLEY_WARN_UNUSED_RESULT
23861     static basic_json from_cbor(InputType&& i,
23862                                 const bool strict = true,
23863                                 const bool allow_exceptions = true,
23864                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23865     {
23866         basic_json result;
23867         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23868         auto ia = detail::input_adapter(std::forward<InputType>(i));
23869         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23870         return res ? result : basic_json(value_t::discarded);
23871     }
23872 
23873     /// @brief create a JSON value from an input in CBOR format
23874     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
23875     template<typename IteratorType>
23876     JSON_HEDLEY_WARN_UNUSED_RESULT
23877     static basic_json from_cbor(IteratorType first, IteratorType last,
23878                                 const bool strict = true,
23879                                 const bool allow_exceptions = true,
23880                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23881     {
23882         basic_json result;
23883         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23884         auto ia = detail::input_adapter(std::move(first), std::move(last));
23885         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23886         return res ? result : basic_json(value_t::discarded);
23887     }
23888 
23889     template<typename T>
23890     JSON_HEDLEY_WARN_UNUSED_RESULT
23891     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23892     static basic_json from_cbor(const T* ptr, std::size_t len,
23893                                 const bool strict = true,
23894                                 const bool allow_exceptions = true,
23895                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23896     {
23897         return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23898     }
23899 
23900     JSON_HEDLEY_WARN_UNUSED_RESULT
23901     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23902     static basic_json from_cbor(detail::span_input_adapter&& i,
23903                                 const bool strict = true,
23904                                 const bool allow_exceptions = true,
23905                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23906     {
23907         basic_json result;
23908         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23909         auto ia = i.get();
23910         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23911         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23912         return res ? result : basic_json(value_t::discarded);
23913     }
23914 
23915     /// @brief create a JSON value from an input in MessagePack format
23916     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23917     template<typename InputType>
23918     JSON_HEDLEY_WARN_UNUSED_RESULT
23919     static basic_json from_msgpack(InputType&& i,
23920                                    const bool strict = true,
23921                                    const bool allow_exceptions = true)
23922     {
23923         basic_json result;
23924         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23925         auto ia = detail::input_adapter(std::forward<InputType>(i));
23926         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23927         return res ? result : basic_json(value_t::discarded);
23928     }
23929 
23930     /// @brief create a JSON value from an input in MessagePack format
23931     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
23932     template<typename IteratorType>
23933     JSON_HEDLEY_WARN_UNUSED_RESULT
23934     static basic_json from_msgpack(IteratorType first, IteratorType last,
23935                                    const bool strict = true,
23936                                    const bool allow_exceptions = true)
23937     {
23938         basic_json result;
23939         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23940         auto ia = detail::input_adapter(std::move(first), std::move(last));
23941         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23942         return res ? result : basic_json(value_t::discarded);
23943     }
23944 
23945     template<typename T>
23946     JSON_HEDLEY_WARN_UNUSED_RESULT
23947     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23948     static basic_json from_msgpack(const T* ptr, std::size_t len,
23949                                    const bool strict = true,
23950                                    const bool allow_exceptions = true)
23951     {
23952         return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23953     }
23954 
23955     JSON_HEDLEY_WARN_UNUSED_RESULT
23956     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23957     static basic_json from_msgpack(detail::span_input_adapter&& i,
23958                                    const bool strict = true,
23959                                    const bool allow_exceptions = true)
23960     {
23961         basic_json result;
23962         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23963         auto ia = i.get();
23964         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23965         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23966         return res ? result : basic_json(value_t::discarded);
23967     }
23968 
23969     /// @brief create a JSON value from an input in UBJSON format
23970     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23971     template<typename InputType>
23972     JSON_HEDLEY_WARN_UNUSED_RESULT
23973     static basic_json from_ubjson(InputType&& i,
23974                                   const bool strict = true,
23975                                   const bool allow_exceptions = true)
23976     {
23977         basic_json result;
23978         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23979         auto ia = detail::input_adapter(std::forward<InputType>(i));
23980         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23981         return res ? result : basic_json(value_t::discarded);
23982     }
23983 
23984     /// @brief create a JSON value from an input in UBJSON format
23985     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
23986     template<typename IteratorType>
23987     JSON_HEDLEY_WARN_UNUSED_RESULT
23988     static basic_json from_ubjson(IteratorType first, IteratorType last,
23989                                   const bool strict = true,
23990                                   const bool allow_exceptions = true)
23991     {
23992         basic_json result;
23993         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23994         auto ia = detail::input_adapter(std::move(first), std::move(last));
23995         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23996         return res ? result : basic_json(value_t::discarded);
23997     }
23998 
23999     template<typename T>
24000     JSON_HEDLEY_WARN_UNUSED_RESULT
24001     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24002     static basic_json from_ubjson(const T* ptr, std::size_t len,
24003                                   const bool strict = true,
24004                                   const bool allow_exceptions = true)
24005     {
24006         return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24007     }
24008 
24009     JSON_HEDLEY_WARN_UNUSED_RESULT
24010     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24011     static basic_json from_ubjson(detail::span_input_adapter&& i,
24012                                   const bool strict = true,
24013                                   const bool allow_exceptions = true)
24014     {
24015         basic_json result;
24016         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24017         auto ia = i.get();
24018         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24019         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
24020         return res ? result : basic_json(value_t::discarded);
24021     }
24022 
24023     /// @brief create a JSON value from an input in BJData format
24024     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24025     template<typename InputType>
24026     JSON_HEDLEY_WARN_UNUSED_RESULT
24027     static basic_json from_bjdata(InputType&& i,
24028                                   const bool strict = true,
24029                                   const bool allow_exceptions = true)
24030     {
24031         basic_json result;
24032         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24033         auto ia = detail::input_adapter(std::forward<InputType>(i));
24034         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
24035         return res ? result : basic_json(value_t::discarded);
24036     }
24037 
24038     /// @brief create a JSON value from an input in BJData format
24039     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24040     template<typename IteratorType>
24041     JSON_HEDLEY_WARN_UNUSED_RESULT
24042     static basic_json from_bjdata(IteratorType first, IteratorType last,
24043                                   const bool strict = true,
24044                                   const bool allow_exceptions = true)
24045     {
24046         basic_json result;
24047         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24048         auto ia = detail::input_adapter(std::move(first), std::move(last));
24049         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
24050         return res ? result : basic_json(value_t::discarded);
24051     }
24052 
24053     /// @brief create a JSON value from an input in BSON format
24054     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24055     template<typename InputType>
24056     JSON_HEDLEY_WARN_UNUSED_RESULT
24057     static basic_json from_bson(InputType&& i,
24058                                 const bool strict = true,
24059                                 const bool allow_exceptions = true)
24060     {
24061         basic_json result;
24062         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24063         auto ia = detail::input_adapter(std::forward<InputType>(i));
24064         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
24065         return res ? result : basic_json(value_t::discarded);
24066     }
24067 
24068     /// @brief create a JSON value from an input in BSON format
24069     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24070     template<typename IteratorType>
24071     JSON_HEDLEY_WARN_UNUSED_RESULT
24072     static basic_json from_bson(IteratorType first, IteratorType last,
24073                                 const bool strict = true,
24074                                 const bool allow_exceptions = true)
24075     {
24076         basic_json result;
24077         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24078         auto ia = detail::input_adapter(std::move(first), std::move(last));
24079         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
24080         return res ? result : basic_json(value_t::discarded);
24081     }
24082 
24083     template<typename T>
24084     JSON_HEDLEY_WARN_UNUSED_RESULT
24085     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24086     static basic_json from_bson(const T* ptr, std::size_t len,
24087                                 const bool strict = true,
24088                                 const bool allow_exceptions = true)
24089     {
24090         return from_bson(ptr, ptr + len, strict, allow_exceptions);
24091     }
24092 
24093     JSON_HEDLEY_WARN_UNUSED_RESULT
24094     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24095     static basic_json from_bson(detail::span_input_adapter&& i,
24096                                 const bool strict = true,
24097                                 const bool allow_exceptions = true)
24098     {
24099         basic_json result;
24100         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
24101         auto ia = i.get();
24102         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24103         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
24104         return res ? result : basic_json(value_t::discarded);
24105     }
24106     /// @}
24107 
24108     //////////////////////////
24109     // JSON Pointer support //
24110     //////////////////////////
24111 
24112     /// @name JSON Pointer functions
24113     /// @{
24114 
24115     /// @brief access specified element via JSON Pointer
24116     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24117     reference operator[](const json_pointer& ptr)
24118     {
24119         return ptr.get_unchecked(this);
24120     }
24121 
24122     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24123     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24124     reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24125     {
24126         return ptr.get_unchecked(this);
24127     }
24128 
24129     /// @brief access specified element via JSON Pointer
24130     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24131     const_reference operator[](const json_pointer& ptr) const
24132     {
24133         return ptr.get_unchecked(this);
24134     }
24135 
24136     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24137     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24138     const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24139     {
24140         return ptr.get_unchecked(this);
24141     }
24142 
24143     /// @brief access specified element via JSON Pointer
24144     /// @sa https://json.nlohmann.me/api/basic_json/at/
24145     reference at(const json_pointer& ptr)
24146     {
24147         return ptr.get_checked(this);
24148     }
24149 
24150     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24151     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24152     reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24153     {
24154         return ptr.get_checked(this);
24155     }
24156 
24157     /// @brief access specified element via JSON Pointer
24158     /// @sa https://json.nlohmann.me/api/basic_json/at/
24159     const_reference at(const json_pointer& ptr) const
24160     {
24161         return ptr.get_checked(this);
24162     }
24163 
24164     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24165     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24166     const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24167     {
24168         return ptr.get_checked(this);
24169     }
24170 
24171     /// @brief return flattened JSON value
24172     /// @sa https://json.nlohmann.me/api/basic_json/flatten/
24173     basic_json flatten() const
24174     {
24175         basic_json result(value_t::object);
24176         json_pointer::flatten("", *this, result);
24177         return result;
24178     }
24179 
24180     /// @brief unflatten a previously flattened JSON value
24181     /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
24182     basic_json unflatten() const
24183     {
24184         return json_pointer::unflatten(*this);
24185     }
24186 
24187     /// @}
24188 
24189     //////////////////////////
24190     // JSON Patch functions //
24191     //////////////////////////
24192 
24193     /// @name JSON Patch functions
24194     /// @{
24195 
24196     /// @brief applies a JSON patch in-place without copying the object
24197     /// @sa https://json.nlohmann.me/api/basic_json/patch/
24198     void patch_inplace(const basic_json& json_patch)
24199     {
24200         basic_json& result = *this;
24201         // the valid JSON Patch operations
24202         enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24203 
24204         const auto get_op = [](const std::string & op)
24205         {
24206             if (op == "add")
24207             {
24208                 return patch_operations::add;
24209             }
24210             if (op == "remove")
24211             {
24212                 return patch_operations::remove;
24213             }
24214             if (op == "replace")
24215             {
24216                 return patch_operations::replace;
24217             }
24218             if (op == "move")
24219             {
24220                 return patch_operations::move;
24221             }
24222             if (op == "copy")
24223             {
24224                 return patch_operations::copy;
24225             }
24226             if (op == "test")
24227             {
24228                 return patch_operations::test;
24229             }
24230 
24231             return patch_operations::invalid;
24232         };
24233 
24234         // wrapper for "add" operation; add value at ptr
24235         const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24236         {
24237             // adding to the root of the target document means replacing it
24238             if (ptr.empty())
24239             {
24240                 result = val;
24241                 return;
24242             }
24243 
24244             // make sure the top element of the pointer exists
24245             json_pointer const top_pointer = ptr.top();
24246             if (top_pointer != ptr)
24247             {
24248                 result.at(top_pointer);
24249             }
24250 
24251             // get reference to parent of JSON pointer ptr
24252             const auto last_path = ptr.back();
24253             ptr.pop_back();
24254             // parent must exist when performing patch add per RFC6902 specs
24255             basic_json& parent = result.at(ptr);
24256 
24257             switch (parent.m_data.m_type)
24258             {
24259                 case value_t::null:
24260                 case value_t::object:
24261                 {
24262                     // use operator[] to add value
24263                     parent[last_path] = val;
24264                     break;
24265                 }
24266 
24267                 case value_t::array:
24268                 {
24269                     if (last_path == "-")
24270                     {
24271                         // special case: append to back
24272                         parent.push_back(val);
24273                     }
24274                     else
24275                     {
24276                         const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24277                         if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24278                         {
24279                             // avoid undefined behavior
24280                             JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24281                         }
24282 
24283                         // default case: insert add offset
24284                         parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24285                     }
24286                     break;
24287                 }
24288 
24289                 // if there exists a parent it cannot be primitive
24290                 case value_t::string: // LCOV_EXCL_LINE
24291                 case value_t::boolean: // LCOV_EXCL_LINE
24292                 case value_t::number_integer: // LCOV_EXCL_LINE
24293                 case value_t::number_unsigned: // LCOV_EXCL_LINE
24294                 case value_t::number_float: // LCOV_EXCL_LINE
24295                 case value_t::binary: // LCOV_EXCL_LINE
24296                 case value_t::discarded: // LCOV_EXCL_LINE
24297                 default:            // LCOV_EXCL_LINE
24298                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24299             }
24300         };
24301 
24302         // wrapper for "remove" operation; remove value at ptr
24303         const auto operation_remove = [this, & result](json_pointer & ptr)
24304         {
24305             // get reference to parent of JSON pointer ptr
24306             const auto last_path = ptr.back();
24307             ptr.pop_back();
24308             basic_json& parent = result.at(ptr);
24309 
24310             // remove child
24311             if (parent.is_object())
24312             {
24313                 // perform range check
24314                 auto it = parent.find(last_path);
24315                 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24316                 {
24317                     parent.erase(it);
24318                 }
24319                 else
24320                 {
24321                     JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24322                 }
24323             }
24324             else if (parent.is_array())
24325             {
24326                 // note erase performs range check
24327                 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24328             }
24329         };
24330 
24331         // type check: top level value must be an array
24332         if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24333         {
24334             JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24335         }
24336 
24337         // iterate and apply the operations
24338         for (const auto& val : json_patch)
24339         {
24340             // wrapper to get a value for an operation
24341             const auto get_value = [&val](const std::string & op,
24342                                           const std::string & member,
24343                                           bool string_type) -> basic_json &
24344             {
24345                 // find value
24346                 auto it = val.m_data.m_value.object->find(member);
24347 
24348                 // context-sensitive error message
24349                 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24350 
24351                 // check if desired value is present
24352                 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24353                 {
24354                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24355                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24356                 }
24357 
24358                 // check if result is of type string
24359                 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24360                 {
24361                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24362                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24363                 }
24364 
24365                 // no error: return value
24366                 return it->second;
24367             };
24368 
24369             // type check: every element of the array must be an object
24370             if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24371             {
24372                 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24373             }
24374 
24375             // collect mandatory members
24376             const auto op = get_value("op", "op", true).template get<std::string>();
24377             const auto path = get_value(op, "path", true).template get<std::string>();
24378             json_pointer ptr(path);
24379 
24380             switch (get_op(op))
24381             {
24382                 case patch_operations::add:
24383                 {
24384                     operation_add(ptr, get_value("add", "value", false));
24385                     break;
24386                 }
24387 
24388                 case patch_operations::remove:
24389                 {
24390                     operation_remove(ptr);
24391                     break;
24392                 }
24393 
24394                 case patch_operations::replace:
24395                 {
24396                     // the "path" location must exist - use at()
24397                     result.at(ptr) = get_value("replace", "value", false);
24398                     break;
24399                 }
24400 
24401                 case patch_operations::move:
24402                 {
24403                     const auto from_path = get_value("move", "from", true).template get<std::string>();
24404                     json_pointer from_ptr(from_path);
24405 
24406                     // the "from" location must exist - use at()
24407                     basic_json const v = result.at(from_ptr);
24408 
24409                     // The move operation is functionally identical to a
24410                     // "remove" operation on the "from" location, followed
24411                     // immediately by an "add" operation at the target
24412                     // location with the value that was just removed.
24413                     operation_remove(from_ptr);
24414                     operation_add(ptr, v);
24415                     break;
24416                 }
24417 
24418                 case patch_operations::copy:
24419                 {
24420                     const auto from_path = get_value("copy", "from", true).template get<std::string>();
24421                     const json_pointer from_ptr(from_path);
24422 
24423                     // the "from" location must exist - use at()
24424                     basic_json const v = result.at(from_ptr);
24425 
24426                     // The copy is functionally identical to an "add"
24427                     // operation at the target location using the value
24428                     // specified in the "from" member.
24429                     operation_add(ptr, v);
24430                     break;
24431                 }
24432 
24433                 case patch_operations::test:
24434                 {
24435                     bool success = false;
24436                     JSON_TRY
24437                     {
24438                         // check if "value" matches the one at "path"
24439                         // the "path" location must exist - use at()
24440                         success = (result.at(ptr) == get_value("test", "value", false));
24441                     }
24442                     JSON_INTERNAL_CATCH (out_of_range&)
24443                     {
24444                         // ignore out of range errors: success remains false
24445                     }
24446 
24447                     // throw an exception if test fails
24448                     if (JSON_HEDLEY_UNLIKELY(!success))
24449                     {
24450                         JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24451                     }
24452 
24453                     break;
24454                 }
24455 
24456                 case patch_operations::invalid:
24457                 default:
24458                 {
24459                     // op must be "add", "remove", "replace", "move", "copy", or
24460                     // "test"
24461                     JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24462                 }
24463             }
24464         }
24465     }
24466 
24467     /// @brief applies a JSON patch to a copy of the current object
24468     /// @sa https://json.nlohmann.me/api/basic_json/patch/
24469     basic_json patch(const basic_json& json_patch) const
24470     {
24471         basic_json result = *this;
24472         result.patch_inplace(json_patch);
24473         return result;
24474     }
24475 
24476     /// @brief creates a diff as a JSON patch
24477     /// @sa https://json.nlohmann.me/api/basic_json/diff/
24478     JSON_HEDLEY_WARN_UNUSED_RESULT
24479     static basic_json diff(const basic_json& source, const basic_json& target,
24480                            const std::string& path = "")
24481     {
24482         // the patch
24483         basic_json result(value_t::array);
24484 
24485         // if the values are the same, return empty patch
24486         if (source == target)
24487         {
24488             return result;
24489         }
24490 
24491         if (source.type() != target.type())
24492         {
24493             // different types: replace value
24494             result.push_back(
24495             {
24496                 {"op", "replace"}, {"path", path}, {"value", target}
24497             });
24498             return result;
24499         }
24500 
24501         switch (source.type())
24502         {
24503             case value_t::array:
24504             {
24505                 // first pass: traverse common elements
24506                 std::size_t i = 0;
24507                 while (i < source.size() && i < target.size())
24508                 {
24509                     // recursive call to compare array values at index i
24510                     auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24511                     result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24512                     ++i;
24513                 }
24514 
24515                 // We now reached the end of at least one array
24516                 // in a second pass, traverse the remaining elements
24517 
24518                 // remove my remaining elements
24519                 const auto end_index = static_cast<difference_type>(result.size());
24520                 while (i < source.size())
24521                 {
24522                     // add operations in reverse order to avoid invalid
24523                     // indices
24524                     result.insert(result.begin() + end_index, object(
24525                     {
24526                         {"op", "remove"},
24527                         {"path", detail::concat(path, '/', std::to_string(i))}
24528                     }));
24529                     ++i;
24530                 }
24531 
24532                 // add other remaining elements
24533                 while (i < target.size())
24534                 {
24535                     result.push_back(
24536                     {
24537                         {"op", "add"},
24538                         {"path", detail::concat(path, "/-")},
24539                         {"value", target[i]}
24540                     });
24541                     ++i;
24542                 }
24543 
24544                 break;
24545             }
24546 
24547             case value_t::object:
24548             {
24549                 // first pass: traverse this object's elements
24550                 for (auto it = source.cbegin(); it != source.cend(); ++it)
24551                 {
24552                     // escape the key name to be used in a JSON patch
24553                     const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24554 
24555                     if (target.find(it.key()) != target.end())
24556                     {
24557                         // recursive call to compare object values at key it
24558                         auto temp_diff = diff(it.value(), target[it.key()], path_key);
24559                         result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24560                     }
24561                     else
24562                     {
24563                         // found a key that is not in o -> remove it
24564                         result.push_back(object(
24565                         {
24566                             {"op", "remove"}, {"path", path_key}
24567                         }));
24568                     }
24569                 }
24570 
24571                 // second pass: traverse other object's elements
24572                 for (auto it = target.cbegin(); it != target.cend(); ++it)
24573                 {
24574                     if (source.find(it.key()) == source.end())
24575                     {
24576                         // found a key that is not in this -> add it
24577                         const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24578                         result.push_back(
24579                         {
24580                             {"op", "add"}, {"path", path_key},
24581                             {"value", it.value()}
24582                         });
24583                     }
24584                 }
24585 
24586                 break;
24587             }
24588 
24589             case value_t::null:
24590             case value_t::string:
24591             case value_t::boolean:
24592             case value_t::number_integer:
24593             case value_t::number_unsigned:
24594             case value_t::number_float:
24595             case value_t::binary:
24596             case value_t::discarded:
24597             default:
24598             {
24599                 // both primitive type: replace value
24600                 result.push_back(
24601                 {
24602                     {"op", "replace"}, {"path", path}, {"value", target}
24603                 });
24604                 break;
24605             }
24606         }
24607 
24608         return result;
24609     }
24610     /// @}
24611 
24612     ////////////////////////////////
24613     // JSON Merge Patch functions //
24614     ////////////////////////////////
24615 
24616     /// @name JSON Merge Patch functions
24617     /// @{
24618 
24619     /// @brief applies a JSON Merge Patch
24620     /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
24621     void merge_patch(const basic_json& apply_patch)
24622     {
24623         if (apply_patch.is_object())
24624         {
24625             if (!is_object())
24626             {
24627                 *this = object();
24628             }
24629             for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24630             {
24631                 if (it.value().is_null())
24632                 {
24633                     erase(it.key());
24634                 }
24635                 else
24636                 {
24637                     operator[](it.key()).merge_patch(it.value());
24638                 }
24639             }
24640         }
24641         else
24642         {
24643             *this = apply_patch;
24644         }
24645     }
24646 
24647     /// @}
24648 };
24649 
24650 /// @brief user-defined to_string function for JSON values
24651 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
24652 NLOHMANN_BASIC_JSON_TPL_DECLARATION
24653 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
24654 {
24655     return j.dump();
24656 }
24657 
24658 inline namespace literals
24659 {
24660 inline namespace json_literals
24661 {
24662 
24663 /// @brief user-defined string literal for JSON values
24664 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
24665 JSON_HEDLEY_NON_NULL(1)
24666 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24667     inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24668 #else
24669     inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24670 #endif
24671 {
24672     return nlohmann::json::parse(s, s + n);
24673 }
24674 
24675 /// @brief user-defined string literal for JSON pointer
24676 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
24677 JSON_HEDLEY_NON_NULL(1)
24678 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24679     inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24680 #else
24681     inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24682 #endif
24683 {
24684     return nlohmann::json::json_pointer(std::string(s, n));
24685 }
24686 
24687 }  // namespace json_literals
24688 }  // namespace literals
24689 NLOHMANN_JSON_NAMESPACE_END
24690 
24691 ///////////////////////
24692 // nonmember support //
24693 ///////////////////////
24694 
24695 namespace std // NOLINT(cert-dcl58-cpp)
24696 {
24697 
24698 /// @brief hash value for JSON objects
24699 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
24700 NLOHMANN_BASIC_JSON_TPL_DECLARATION
24701 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24702 {
24703     std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24704     {
24705         return nlohmann::detail::hash(j);
24706     }
24707 };
24708 
24709 // specialization for std::less<value_t>
24710 template<>
24711 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24712 {
24713     /*! 
24714     @brief compare two value_t enum values 
24715     @since version 3.0.0 
24716     */
24717     bool operator()(::nlohmann::detail::value_t lhs,
24718                     ::nlohmann::detail::value_t rhs) const noexcept
24719     {
24720 #if JSON_HAS_THREE_WAY_COMPARISON
24721         return std::is_lt(lhs <=> rhs); // *NOPAD*
24722 #else
24723         return ::nlohmann::detail::operator<(lhs, rhs);
24724 #endif
24725     }
24726 };
24727 
24728 // C++20 prohibit function specialization in the std namespace.
24729 #ifndef JSON_HAS_CPP_20
24730 
24731 /// @brief exchanges the values of two JSON objects
24732 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
24733 NLOHMANN_BASIC_JSON_TPL_DECLARATION
24734 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24735     is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24736     is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24737 {
24738     j1.swap(j2);
24739 }
24740 
24741 #endif
24742 
24743 }  // namespace std
24744 
24745 #if JSON_USE_GLOBAL_UDLS
24746     #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24747         using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24748         using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24749     #else
24750         using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24751         using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24752     #endif
24753 #endif
24754 
24755 // #include <nlohmann/detail/macro_unscope.hpp>
24756 //     __ _____ _____ _____
24757 //  __|  |   __|     |   | |  JSON for Modern C++
24758 // |  |  |__   |  |  | | | |  version 3.11.3
24759 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
24760 //
24761 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
24762 // SPDX-License-Identifier: MIT
24763 
24764 
24765 
24766 // restore clang diagnostic settings
24767 #if defined(__clang__)
24768     #pragma clang diagnostic pop
24769 #endif
24770 
24771 // clean up
24772 #undef JSON_ASSERT
24773 #undef JSON_INTERNAL_CATCH
24774 #undef JSON_THROW
24775 #undef JSON_PRIVATE_UNLESS_TESTED
24776 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24777 #undef NLOHMANN_BASIC_JSON_TPL
24778 #undef JSON_EXPLICIT
24779 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24780 #undef JSON_INLINE_VARIABLE
24781 #undef JSON_NO_UNIQUE_ADDRESS
24782 #undef JSON_DISABLE_ENUM_SERIALIZATION
24783 #undef JSON_USE_GLOBAL_UDLS
24784 
24785 #ifndef JSON_TEST_KEEP_MACROS
24786     #undef JSON_CATCH
24787     #undef JSON_TRY
24788     #undef JSON_HAS_CPP_11
24789     #undef JSON_HAS_CPP_14
24790     #undef JSON_HAS_CPP_17
24791     #undef JSON_HAS_CPP_20
24792     #undef JSON_HAS_FILESYSTEM
24793     #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24794     #undef JSON_HAS_THREE_WAY_COMPARISON
24795     #undef JSON_HAS_RANGES
24796     #undef JSON_HAS_STATIC_RTTI
24797     #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24798 #endif
24799 
24800 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24801 //     __ _____ _____ _____
24802 //  __|  |   __|     |   | |  JSON for Modern C++
24803 // |  |  |__   |  |  | | | |  version 3.11.3
24804 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
24805 //
24806 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me>
24807 // SPDX-License-Identifier: MIT
24808 
24809 
24810 
24811 #undef JSON_HEDLEY_ALWAYS_INLINE
24812 #undef JSON_HEDLEY_ARM_VERSION
24813 #undef JSON_HEDLEY_ARM_VERSION_CHECK
24814 #undef JSON_HEDLEY_ARRAY_PARAM
24815 #undef JSON_HEDLEY_ASSUME
24816 #undef JSON_HEDLEY_BEGIN_C_DECLS
24817 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24818 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24819 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24820 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24821 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24822 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
24823 #undef JSON_HEDLEY_CLANG_HAS_WARNING
24824 #undef JSON_HEDLEY_COMPCERT_VERSION
24825 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24826 #undef JSON_HEDLEY_CONCAT
24827 #undef JSON_HEDLEY_CONCAT3
24828 #undef JSON_HEDLEY_CONCAT3_EX
24829 #undef JSON_HEDLEY_CONCAT_EX
24830 #undef JSON_HEDLEY_CONST
24831 #undef JSON_HEDLEY_CONSTEXPR
24832 #undef JSON_HEDLEY_CONST_CAST
24833 #undef JSON_HEDLEY_CPP_CAST
24834 #undef JSON_HEDLEY_CRAY_VERSION
24835 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
24836 #undef JSON_HEDLEY_C_DECL
24837 #undef JSON_HEDLEY_DEPRECATED
24838 #undef JSON_HEDLEY_DEPRECATED_FOR
24839 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24840 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24841 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24842 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24843 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24844 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24845 #undef JSON_HEDLEY_DIAGNOSTIC_POP
24846 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24847 #undef JSON_HEDLEY_DMC_VERSION
24848 #undef JSON_HEDLEY_DMC_VERSION_CHECK
24849 #undef JSON_HEDLEY_EMPTY_BASES
24850 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24851 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24852 #undef JSON_HEDLEY_END_C_DECLS
24853 #undef JSON_HEDLEY_FLAGS
24854 #undef JSON_HEDLEY_FLAGS_CAST
24855 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24856 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
24857 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24858 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24859 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
24860 #undef JSON_HEDLEY_GCC_HAS_FEATURE
24861 #undef JSON_HEDLEY_GCC_HAS_WARNING
24862 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24863 #undef JSON_HEDLEY_GCC_VERSION
24864 #undef JSON_HEDLEY_GCC_VERSION_CHECK
24865 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24866 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24867 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24868 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24869 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24870 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
24871 #undef JSON_HEDLEY_GNUC_HAS_WARNING
24872 #undef JSON_HEDLEY_GNUC_VERSION
24873 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
24874 #undef JSON_HEDLEY_HAS_ATTRIBUTE
24875 #undef JSON_HEDLEY_HAS_BUILTIN
24876 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24877 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24878 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24879 #undef JSON_HEDLEY_HAS_EXTENSION
24880 #undef JSON_HEDLEY_HAS_FEATURE
24881 #undef JSON_HEDLEY_HAS_WARNING
24882 #undef JSON_HEDLEY_IAR_VERSION
24883 #undef JSON_HEDLEY_IAR_VERSION_CHECK
24884 #undef JSON_HEDLEY_IBM_VERSION
24885 #undef JSON_HEDLEY_IBM_VERSION_CHECK
24886 #undef JSON_HEDLEY_IMPORT
24887 #undef JSON_HEDLEY_INLINE
24888 #undef JSON_HEDLEY_INTEL_CL_VERSION
24889 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24890 #undef JSON_HEDLEY_INTEL_VERSION
24891 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
24892 #undef JSON_HEDLEY_IS_CONSTANT
24893 #undef JSON_HEDLEY_IS_CONSTEXPR_
24894 #undef JSON_HEDLEY_LIKELY
24895 #undef JSON_HEDLEY_MALLOC
24896 #undef JSON_HEDLEY_MCST_LCC_VERSION
24897 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24898 #undef JSON_HEDLEY_MESSAGE
24899 #undef JSON_HEDLEY_MSVC_VERSION
24900 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
24901 #undef JSON_HEDLEY_NEVER_INLINE
24902 #undef JSON_HEDLEY_NON_NULL
24903 #undef JSON_HEDLEY_NO_ESCAPE
24904 #undef JSON_HEDLEY_NO_RETURN
24905 #undef JSON_HEDLEY_NO_THROW
24906 #undef JSON_HEDLEY_NULL
24907 #undef JSON_HEDLEY_PELLES_VERSION
24908 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
24909 #undef JSON_HEDLEY_PGI_VERSION
24910 #undef JSON_HEDLEY_PGI_VERSION_CHECK
24911 #undef JSON_HEDLEY_PREDICT
24912 #undef JSON_HEDLEY_PRINTF_FORMAT
24913 #undef JSON_HEDLEY_PRIVATE
24914 #undef JSON_HEDLEY_PUBLIC
24915 #undef JSON_HEDLEY_PURE
24916 #undef JSON_HEDLEY_REINTERPRET_CAST
24917 #undef JSON_HEDLEY_REQUIRE
24918 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24919 #undef JSON_HEDLEY_REQUIRE_MSG
24920 #undef JSON_HEDLEY_RESTRICT
24921 #undef JSON_HEDLEY_RETURNS_NON_NULL
24922 #undef JSON_HEDLEY_SENTINEL
24923 #undef JSON_HEDLEY_STATIC_ASSERT
24924 #undef JSON_HEDLEY_STATIC_CAST
24925 #undef JSON_HEDLEY_STRINGIFY
24926 #undef JSON_HEDLEY_STRINGIFY_EX
24927 #undef JSON_HEDLEY_SUNPRO_VERSION
24928 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24929 #undef JSON_HEDLEY_TINYC_VERSION
24930 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
24931 #undef JSON_HEDLEY_TI_ARMCL_VERSION
24932 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24933 #undef JSON_HEDLEY_TI_CL2000_VERSION
24934 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24935 #undef JSON_HEDLEY_TI_CL430_VERSION
24936 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24937 #undef JSON_HEDLEY_TI_CL6X_VERSION
24938 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24939 #undef JSON_HEDLEY_TI_CL7X_VERSION
24940 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24941 #undef JSON_HEDLEY_TI_CLPRU_VERSION
24942 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24943 #undef JSON_HEDLEY_TI_VERSION
24944 #undef JSON_HEDLEY_TI_VERSION_CHECK
24945 #undef JSON_HEDLEY_UNAVAILABLE
24946 #undef JSON_HEDLEY_UNLIKELY
24947 #undef JSON_HEDLEY_UNPREDICTABLE
24948 #undef JSON_HEDLEY_UNREACHABLE
24949 #undef JSON_HEDLEY_UNREACHABLE_RETURN
24950 #undef JSON_HEDLEY_VERSION
24951 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24952 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
24953 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
24954 #undef JSON_HEDLEY_VERSION_ENCODE
24955 #undef JSON_HEDLEY_WARNING
24956 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
24957 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24958 #undef JSON_HEDLEY_FALL_THROUGH
24959 
24960 
24961 
24962 #endif  // INCLUDE_NLOHMANN_JSON_HPP_
24963